You are on page 1of 71

Programski jezik

RUBY
NAJLAKŠI PROGRAMSKI
JEZIK

-----------------------------------------------
© 2003-2009 Chris Pine
http://pine.fm/LearnToProgram/

-1-
#. Uvod
Predgovor prevodioca

U ime Milostivog i Svemilosnog Boga,

U potrazi za stabilnim okruženjem koje će mi pomoći da razvijem open source program za


obradu podataka na hematološkim klinikama i zavodima za transfuzijsku medicinu, naišao
sam na Ruby, za svijet programiranja relativno nov jezik. Svi su ukazivali na jednostavnost
ovog programskog jezika, a kako su moja prva iskustva u programiranju bila sa jezikom
BASIC, za koji svi smijemo reći da je prilično jednostavan, pomislio sam kako bi dobro
MySQL bazu povezati sa Ruby, ako je tako jednostavna i bio sam ubijeđen da sam pronašao
savršenu platformu za moju buduću aplikaciju. Postoji danas mnogo različitih tutoriala,
knjiga, uputstava i dokumentacije koja u glavi uglavnom proizvede vertigo – vrtoglavicu, a ne
jasnu predstavu o programskom jeziku. Tutorial koji je napisao gospodin Kris Pajn (Chris
Pine) je nešto drukčiji. On se postavlja prema onima koji tek uče Ruby kao da i on sam tek
počinje s programiranjem...ustvari, tutorial to i jeste – on je za početnike u programiranju, one
koji debituju, samo što im kao primarni jezik u programiranju postavlja Ruby. Iz tog razloga
sam i tražio njegovu dozvolu da tutorial koji je napisao prevedem na bosanski jezik (što
podrazumijeva da ga razumije i veliki broj drugih Južnih Slavena, ne samo Bosanci i
Hercegovci, nego Hrvati, Srbi, Crnogorci, Makedonci, Albanci, ...mnogi drugi, te Slovenci).
Nisam našao nikakav sličan u našem govornom području (ustvari, nisam uopšte našao tutorial
na nekom od jezika ex-YU naroda kojemu je tema Ruby ili uvod u programiranje – sličan
konceptu kojeg Kris ima), pa sam pomislio kako bi bilo lijepo dati neki doprinos. Prijevod
ovog tutoriala nije doslovan i izmjene u njemu imaju cilj da Ruby što bolje približe
apsolutnom početniku. U par slučajeva (naslovima ili opisima), za neke definicije sam bio
prinuđen koristiti izvorne nazive (koji potiču iz engleskog jezika), koji se inače koriste u
programiranju, da bih opisao neke od elemenata sintakse koju koristi Ruby. Imajući u vidu da
se budući programer zaista mora dobro snalaziti s engleskim jezikom, mislim kako izvorni
nazivi neće predstavljati veći problem. Bude li među čitaocima ovog tutoriala onih koji mu
nađu mahane, neka se slobodno jave, da eventualne nedostatke mogu što prije ispraviti.
Dodatak: komentare prevodica, kojih je zaista malo, označavao sam [k.p.:]

Rusmir Gadžo (rusmirgadzo@gmail.com)


[http://sites.google.com/site/rubynabosanskom/]
Februar] [Veljača 2009 / Safer 1430

Dobar početak za budućeg programera

Sve je počelo negdje 2002 godine. Razmišljao sam kako bih mogao podučavati programiranju
i kako bi divan jezik Ruby bio za to. Mislim, svi smo mi bili uzbuđeni kad je Ruby došao, jer
smo uvidjeli kako je moćan, elegantan i stvarno jako zabavan jezik, ali meni se činilo da bi to
takođe bio dobar jezik za one koji tek ulaze u programiranje.

Nažalost, u to vrijeme nije bilo mnogo priručnika ili neke druge dokumentacije za Ruby
početnike. Neki od nas, u programerskoj zajednici, pitali su se šta zaista treba da sadrži jedan
„Ruby za početnika“ tutorial i kako pristupiti podučavanju programiranja uopšte. Što sam više
razmišljao o ovome, više sam imao za reći (što me je pomalo iznenadilo). Konačno, neko mi
je rekao „Kris, zašto jednostavno ne napišeš tutorial, umjesto što stalno pričaš o njemu?“
Tako sam i učinio.

-2-
Nije mi išlo baš najbolje. Sve moje ideje su nekako bile dobre u teoriji, ali konkretan zadatak
pisanja sjajnog tutoriala za one koji tek ulaze u programiranje bio je priličan izazov, veći nego
sam zamišljao. (Meni se tutorial činio dobrim, ali ja sam već poznavao programiranje.)

Spasilo me je to što sam olakšao ljudima kontakt sa mnom, pa sam im tako mogao pomoći
svaki put kad bi nešto „zapelo“. Kad bih vidio da mnogo njih „zapinje“ na jednom (istom)
mjestu, onda bih se potrudio da taj dio izmjenim, napišem ponovo. Bilo je tu dosta posla, ali
je lagano postajalo sve bolje i bolje.

Par godina nakon toga, postao je to jedan stvarno dobar tutorial J. Ustvari, tako dobar, da sam
bio spreman proglasiti ga završenim, tako da bih mogao preći na nešto drugo. Upravo tada se
ukazala prilika da se moj tutorial pretvori u knjigu. Pošto je, u suštini, bio završen, nisam
imao ništa protiv da se objavi kao knjiga. Jednostavno bih dodao par novih tačaka, par novih
vježbi, možda koji primjer više, par novih poglavlja, pronašao 50-tak ljudi za recenziju...

Radio sam na tome još jednu godinu, ali sada mislim da je tutorial jako dobar, većinom iz
razloga što mi je u pomoć priteklo stotine hrabrih duša.

Ono što stoji ovdje je originalni tutorial, manje-više izmjenjen od 2004. godine. Za ono
najbolje i najnovije, trebalo bi pogledati kako izgleda moja knjiga.

 
Par savjeta za predavače
Postoji nekoliko principa kojih sam se pokušao držati dok sam pisao ovaj tutorial. Mislim da
ti principi čine da proces učenja programskog jezika teče lakše; učiti programiranje je ionako
teško, samo od sebe. Ako ste od onih koji nekoga podučavaju kako uploviti u vode „hackera“
onda bi i vama ove ideje mogle biti od pomoći.

Prvo, pokušao sam razdvojiti koncepte, što je više moguće, tako da bi učenik učio samo jedan
koncept. Ispočetka je išlo teško, ali nakon malo vježbe bilo je i previše lahko. Neke se stvari
moraju naučiti prije onih na koje dolazimo, ali sam bio iznenađen što je zaista vrlo malo
hijerarhije pređašnjosti (poznavanja prethodnog gradiva) bilo uključeno. Na kraju, trebalo je
samo da poredam stvari, a pokušao sam da ih uredim tako da bi novi naslovi bili motivirani
onim prošlim.

Još jedan od principa kojih sam se držao je podučiti ljude da postoji samo jedan način da
nešto naprave. Očigledna je to beneficija za ljude koji nikad nisu programirali. Jedno je
sigurno, jedan način da se nešto napravi je lakše naučiti nego dva. Možda je važnije to da, što
manje stvari naučite programera, to će više do izražaja doći njegova kreativnost i pamet u
programiranju. Iz razloga što se većina stvari u programiranju svodi na riješavanje problema,
od ključne je važnosti da se budući programeri što više potiču na to u svakoj fazi
podučavanja.

Pokušao sam uključiti neke programerske koncepte u koncepte koje ljudi već imaju kod sebe,
u životu, da bih prezentovao ideje na takav način da je njihova intuicija ono na što će se
osloniti, a ne tutorial. Objektno-orijentisano programiranje se jako dobro uklapa u ovakav
koncept. Zbog toga sam vrlo rano mogao da počnem sa naglašavanjem „objekata“ i različitih
„vrsta objekata“ , izgovarajući te fraze bez ustručavanja. Nisam koristio izraze kao što su „sve
u Ruby je objekat“ ili „brojevi i znakovi su vrste objekata“, iz razloga što što ovi izrazi ne
znače ništa onome ko tek stupa u programiranje. Umjesto toga, pričao bih samo o znakovima
(ne „znakovnim objektima“), a ponekad bih o objektima govorio samo kao „stvarima“ u
nekom od programa. To što sam, pomalo podmuklo J, rekao za objekte u Ruby da su „stvari u
programima“, imalo je velikog uspjeha.

-3-
Kada bih svoje učenike podučavao, pokušao bih da izbjegnem nepotrebni žargon, pa ako bi
trebali naučiti neki od naziva, onda bih se potrudio da to bude onaj pravi; tako sam znakove
nazivao „strings“, a ne tekstom. I metode sam nekako morao nazvati, pa kako bih drukčije
nego „methods“.

Što se vježbanja tiče, mislim da sam izmilslio par vježbi koje su jako dobre, ali njih svakako
nikad nije dosta. Iskreno, mislim da sam pola svoga vremena potrošio samo smišljajući
zabavne, zanimljive vježbice. Dosadna vježba ubija želju za programiranjem, dok savršena
vježba kod novopečenog programera pravi svrab koji jednostavno mora počešati! Ukratko,
kad se prave dobre vježbe, tu ne možete nikad provesti previše vremena.

 
O originalnom tutorialu
Stranice ovog tutoriala generiše jedan poveći program napisan u Ruby, naravno :). Kao takav,
ima par zanimiljivih osobina. Na primjer, svi primjeri programskog koda izvršavaju se svaki
put kad se stranica učita i prikazani ispis je ispis koji program generiše. Mislim da je ovo
najbolji i najlakši način da se osigura da sav kod koji prezentiram radi tačno onako kako ja to
kažem. Ne morate se brinuti da li sam kopirao ispis nekog od primjera pogrješno ili zaboravio
testirati dio koda; svaki put kad ga čitate, on istovremeno bude i testiran (odnosi se na webiste
autora: http://pine.fm/LearnToProgram/). Tako, na primjer, u odjeljku koji govori o
generisanju slučajne cifre, svaki put kad učitate stranicu, imaćete priliku da vidite novi
broj...zgodno! (Koristio sam isti trik i u kodu koji sam dao kako primjer kad sam pisao knjigu,
ali očigledno je da se efekti daju lakše uočiti u ovom tutorialu.)

Priznanja
Konačno, htio bih da se zahvalim učesnicima ruby-talk mailing liste na njihovim zamislima,
prijedlozima i ohrabrenjima, svim mojim divnim recenzentima na njihovoj pomoći da knjigu
učinim boljom nego bi ona bila kad bih je pisao ja sam, mojoj voljenoj supruzi, jer je bilo moj
glavni recenzent/tester/pokusni kunić/muza, Matzu jer je napravio ovaj sjajni jezik i
Pragmatic Programmers jer su me s njim upoznali i naravno, objavili moju knjigu!

Ukoliko uočite kakve grješke ili imate komentar ili prijedlog, možda dobru vježbu koju bih
mogao uvrstiti, slobodno to podijelite sa mnom putem ove adrese: e-mail

0. Da počnemo...
Programirati na računaru, to znači "govoriti" jezikom koji naš računar razumije: programskim jezikom. Danas
je u opticaju mnogo različtih programskih jezika i među njima ima onih koji su izvrsni. Za ovaj tutorial,
odabrao sam moj omiljeni programski jezik, Ruby.

Osim što je moj omiljeni, Ruby je takođe i najjednostavniji programski jezik koji sam ikad vidio (a vidio sam
stvarno dosta njih u karijeri). Ustvari, to je razlog zbog kojeg pišem ovaj tutorial: nisam odlučio napisati ga i
odabrati Ruby samo zato što je moj omiljeni; naprotiv, otkrio sam da je Ruby jako jednostavan programski
jezik i da bi za njega trebao postojati dobar tutorial za početnike. Dakle, jednostavnost Ruby kao programskog
jezika potakla je pisanje ovog tutoriala, a ne činjenica da je to moj omiljeni jezik. (Pisanje sličnog tutoriala za
neki drugi programski jezik, kao što je Java ili C++, zahtijevalo bi par stotina stranica). Nemojte pomisliti da
je Ruby početnički jezik iz razloga što je tako jednostavan. Ruby je moćan programski jezik, čija jačina u
profesiji je možda najveća do sada viđena.

Kad pišete nešto što je ravno govoru čovjeka, onda to nazivamo tekstom. Kad pišete nešto što je ravno govoru
računara, onda već govorimo o nečemu što se u profesiji programera naziva kod. U ovaj sam tutorial uvrstio
-4-
dosta primjera Ruby koda, a većina tog koda su kompletni programi koje i sami možete pokrenuti na svom
računaru. Da bih olakšao čitanje koda, obojio sam neke njegove dijelove različitim bojama. (Npr., brojevi
imaju uvijek zelenu boju). Sve što će biti unijeto putem tastature (input) biće na bijeloj, a sve što će program
dati kao rezultat biće na plavoj podlozi (output).

Ukoliko naiđete na dijelove koje ne razumijete, ili imate pitanje na koje nije ponuđen odgovor, zapišite to
pitanje i nastavite čitati! Moguće je da će taj odgovor doći sam u nekom od narednih poglavlja. Međutim, ako
odgovor ne dobijete do posljednjeg poglavlja, spreman sam vam pomoći da ga nađete. Mnogo je divnih ljudi
koji su spremni da pomognu, samo treba znati gdje se oni nalaze.

No, prvo što trebamo učiniti je - instalirati Ruby na računar.

INSTALACIJA NA WINDOWS OPERATIVNI SISTEM

Instalirati Ruby na Windows operativni sistem je prilično lahko. Prvi na listi zadataka je download Ruby
installera. Vjerovatno ćete naići na nekoliko različitih verzija, dostupnih za download; ovaj tutorial koristi
verziju 1.8.4, tako da bi bilo dobro da i vaša instalacija bude makar u nivou te verzije. (Najbolje bi bilo
odabrati posljednju – najnoviju verziju). Nakon što je download završen, pokreće se najobičnija instalacija,
kao i za većinu Windows aplikacija. Tokom instalacije ćete biti upitani u koji folder/direktorij želite smjestiti
Ruby. Ruby je najbolje smjestiti u „default location“, osim ako vi nemate neki poseban razlog zbog kojeg to
ne želite učiniti.

Da biste mogli programirati, potrebni su vam alati koji će omogućiti pisanje koda i njegovo izvršavanje. Za
sve to će biti potreban program za uređivanje teksta i „komandna linija“.

Ruby installer dolazi sa dražesnim uređivačem teksta nazvanim SciTE (the Scintilla Text Editor). Možete ga
pokrenuti iz „Start“ menija. Ukoliko želiti imati obojen kod, kao što je to u ovom tutorijalu, onda postavite
fajlove koje ću vam navesti ispod u SciTeov folder/direktorij (ako ste Ruby instalirali u „default location“
onda je putanja do ovog foldera: c:/ruby/scite).

Global properties
Ruby properties

Ne bi bilo loše imati negdje zaseban folder u kome će biti smješteni programi, odnosno kod koji napišete. Kad
završite s programiranjem, pobrinite se da program koji ste napisali spasite u taj folder/direktorij. Komandnu
liniju najjednostavnije je koristiti preko integrisanog „Command prompt“-a koji je integrisan u sam Windows,
a može ga se naći u Start->All programs>Accessories. Tipične komande „cd“ i „dir“ daće vam uvid u putanju
u kojoj se trenutno nalazite, a možete ih koristiti i da dođete do foldera/direktorija u kome su smješteni
programi koje ste napisali.

To bi bilo sve! Sad ste već spremni učiti programiranje.

INSTALACIJA NA MAC OPERATIVNI SISTEM


Ukoliko radite na Mac OS X 10.2 (Jaguar) operativnom sistemu, onda je Ruby već instaliran na vaš računar.
Je l' moglo biti lakše? Mislim da, nažalost, na verzijama sistema manjim od ove (uključuje 10.1 i manje) Ruby
ne dolazi instaliran.

Da biste mogli programirati, potrebni su vam alati koji će omogućiti pisanje koda i njegovo izvršavanje. Za
sve to će biti potreban program za uređivanje teksta i „komandna linija“.

Komandna linija dostupna je preko Terminala (koji se nalazi u Applications/Utilities).

-5-
Uređivača teksta što se tiče, možete koristiti bilo koji, koji vama lično pogoduje. Ukoliko koristite TextEdit,
budite sigurni da programe koje napišete spasite kao „text-only“, u protivnom vaši programi neće raditi.
Alternativne opcije su emacs, vi ili pico i svi su dostupni preko komandne linije.

To bi bilo sve! Sad ste već spremni učiti programiranje.

INSTALACIJA NA LINUX OPERATIVNI SISTEM


Prije svega, treba provjeriti da li je Ruby već instalirana na distribuciju Linux operativnog sistema kojeg
koristite. Ukucajte u komandnu liniju (terminal) „which ruby“. Ukoliko kao odgovor dobijete nešto kao
„/usr/bin/which: no ruby in (...)“, onda morate obaviti download. U suprotnom, provjerite koju verziju Ruby
vaša distribucija uključuje komandom „with ruby –v“ . Ukoliko je starija od posljednjeg stabilnog izdanja
koje je dostupno, onda bi bilo lijepo napraviti upgrade.

Ukoliko imate privilegije „root“ korisnika, onda vam vjerovatno ne trebaju posebne upute za instalaciju Ruby.
Međutim, ako to nije slučaj, onda ćete tražiti od administratora vašeg sistema da to učini za vas (na taj način
bi svi koji pristupaju tom sistemu bili u mogućnosti da ga koriste).

Ukoliko želite instalirati Ruby samo za određenog korisnika, onda usmjerite dowloadiranu instalaciju u neki
trenutni folder/direktorij, npr. $HOME/tmp. Ako je ime fajla koji ste downloadirali ruby-1.6.7.tar.gz, onda ga
možete otvoriti komandom „tar zxvf ruby-1.6.7.tar.gz“. Pristupite folderu/direktoriju koji ste upravo napravili
za tu svrhu ($HOME/tmp – „tmp“ ime koje ste mu odlučili dati) komandom „cd tmp“).

Konfigurišite prvo instalaciju komandom „./configure –prefix=$HOME“. Nakon toga u komandnu liniju
upišite „make“,...ona bi trebala izgraditi vaš Ruby interpreter...što bi moglo potrajati koji minut. Po završetku
tog procesa unesite komandu „make install“, da bi instalacija konačno bila izvršena.

Poslije instalacije bi trebalo dodati „$HOME/bin“ folder/direktorij u tražilicu komandne linije editovanjem
„$HOME/.bashrc“ fajla. (Da bi izmjene bile prihvaćene, potrebno je uraditi logout i nakon toga ponovo ući u
sistem). Po ponovnom pristupanju sistemu (login), testirajte je li instalacija uspjela komandom „ruby –v“.
Ukoliko u outputu dobijete verziju Ruby, znači da je instalacija bila uspješna i da $HOME/tmp
folder/direktorij (ili kako god ga vi nazvali) možete slobodno brisati.

To bi bilo sve! Sad ste već spremni učiti programiranje.

-6-
1. Brojevi
Sad kad je sve podešeno, instalacija izvršena, hajde da napišemo program. Otvorite svoj omiljeni uređivač
teksta i upišite slijedeće:

puts 1+2

Spasite program (da, da, to je program!) kao calc.rb (*.rb je ekstenzija koju obično stavljamo programima
napisanim u Ruby). Pokrenite sada taj program upisujući calc.rb u komandnu liniju. Na ekranu bi se kao
rezultat trebao ispisati “3”. Vidite, programiranje i nije tako teško, zar ne?

Predstavljamo komandu „puts“


Dakle, šta program koji smo napisali radi? Siguran sam da ćete od prve pogoditi šta će biti rezultat
komande 1 + 2; naš je program, u suštini, isti kao:

puts 3

„puts“ dakle, ispisuje na ekran sve ono što se nalazi ispred njega.

Cijeli i decimalni brojevi


U većini programskih jezika (Ruby nije nikakva iznimka) brojevi bez decimale nazvani su „integers“, a
brojevi sa decimalnim zarezom nazvani su „floating-point“ ili jednostavnije „floats“.

Evo primjera par integers: 5 -205 999999999 0

A tu je i par floats: 54.321 0.001 -205.3884

U praksi, većina programa ne koristi floats, samo integers (uostalom, ko još želi pregledati 7.4 e-mail, ili
1.8 web stranica ili slušati 5.24 omiljenih pjesama). Floats se koriste više za akademske svrhe (pokuse u
fizici i sl.) i za 3D grafiku. Čak i većina programera koji rade aplikacije koje upravljaju novcem koriste
integers; siću prate cjelobrojnim vrijednostima!

Jednostavna aritmetika
Do sada smo uspjeli napraviti najjednostavniji kalkulator. (Kalkulatori uvijek koriste floats, pa tako, ako
želite napraviti digitron od svog računara, trebali biste takođe koristiti isti). Kao što smo mogli vidjeti, za
sabiranje i oduzimanje se koriste znakovi [+] i [-]. Kod većine tastatura/tipkovnica, ovi su dugmići
smješteni krajnje desno, a ukoliko imate laptop onda je to kombinacija Shift+8 i Shift+/ (za: english
keyboard layout). Hajde da sad malo proširimo naš calc.rb program. Dodajte u program slijedeće linije i
onda ga pokrenite:

puts 1.0 + 2.0


puts 2.0 * 3.0
puts 5.0 - 8.0
puts 9.0 / 2.0

Ono što će program vratiti kao ispis biće:


-7-
3.0
6.0
-3.0
4.5

(Razmaci koji se vide u programu – između rezervisanih riječi i vrijednosti – nisu od važnosti; oni samo
pomažu da se kod lakše čita.)
Dobro, to i nije bilo baš iznenađujuće. Hajde da pokušamo sa integers:

puts 1+2
puts 2*3
puts 5-8
puts 9/2

Uglavnom isto, zar ne?

3
6
-3
4

Pardon…osim onog zadnjeg! Ali, tako vam je kad radite aritmetiku sa integers - dobijete i cjelobrojnu
vrijednost. Kad vaš računar me može da nađe “pravi” odgovor, onda ga on uvijek zaokruži. (Naravno, za
cjelobrojnu aritmetiku, 9/2 = 4 je tačan odgovor, iako možda i nije onaj koji smo očekivali.)

Pitate se vjerovatno, za kakvu je svrhu dijeljenje integerom dobro. Recimo da idete u kino, ali imate samo
9$. Ovdje u Portlandu, možete pogledati film u “Bagdadu” za dva dolara. Koliko to onda filmova možete
pogledati? 9/2…4 filma. Četiri i pola sigurno nije tačan odgovor u ovom slučaju; neće vas baš pustiti da
pogledate polovinu filma, ili pak dozvoliti polovini vas (kao čovjeka ili žene) da pogledate cijeli film…
neke stvari jednostavno nisu djeljive na taj način.

Sad već imate slobodu da sami pišete svoje programe! Ako želite uvrstiti malo složenije izraze, koristite
zagrade. Evo par primjera:

puts 5 * (12-8) + -15


rezultira: 5

puts 98 + (59872 / (13*8)) * -52


rezultira: -29802

Par stvarčica za probati…


Napišite program koji će vam reći:
 koliko sati ima u jednoj godini?
 koliko minuta ima u jednoj dekadi (deset godina)?
 koliko ste sekundi stari?
 koliko čokolada se nadate da bi mogli pojesti u životu?

-8-
Evo malo težeg pitanja:
 Koliko sam star, ako imam 1025 miliona sekundi života?

Ukoliko ste završili igru s brojevima, onda možemo preći na slova.

2. Slova
Dakle, naučili smo ponešto o brojkama, ali šta je sa slovima, riječima, tekstom? Grupu znakova u jednom
programu nazivamo skupnom oznakom „strings“ (znakovni niz). (Možete ih zamisliti kao slova
štampanim na nekoj reklami.) Da jednostavnije objasnimo koji dio kod pripada stringu, bojićemo ih u
crveno. Slijedi par primjera:

'Hello.'
'Ruby rocks.'
'5 is my favorite number... what is yours?'
'Snoopy says #%^?&*@! when he stubs his toe.'
' '
''

Kao što možete vidjeti, strings mogu imati ne samo slova nego i ostale znakove. Poslijednji primjer, u
kome nema nikakvih znakova nazvali bismo praznim ili “empty string”.
Koristili smo naredbu „puts” za ispis brojeva, hajde da pokušamo isto i sa strings:

puts 'Hello, world!'


puts ''
puts 'Good-bye.'

Ispis bi izgledao ovako:

Hello, world!

Good-bye.

To je dobro ispalo. Pokušajte sami napisati nekoliko primjera, proizvoljno.

Aritmetika znakovnog niza (string)


Baš onako kako izvodimo aritmetičke operacije nad brojevima, moguće ih je izvoditi i nad slovima,
odnosno znakovima (strings). Pa, dobro,...nekako već možemo dodati stringove jedne drugima. Hajde da
pokušamo dodati jedan string drugome, pa da vidimo kakav će ispis na ekranu biti.

puts 'I like' + 'apple pie.'

-9-
Ispis:
I likeapple pie.

Opaaa! Zaboravih napraviti razmak između „I like” i „apple pie”. Razmaci uglavnom nisu toliko važni,
generalno, ali su važni unutar stringa. (Istina je ono što pričaju: računari ne rade ono što mi od njih želimo
da urade, nego ono što im kažemo/naredimo.) Hajde da pokušamo ponovo:

puts 'I like ' + 'apple pie.'


puts 'I like' + ' apple pie.'

Ispis:
I like apple pie.
I like apple pie.

(Kao što možete uočiti, nije važno kojem stringu sam dodao razmak.) Dakle, moguće je „adirati” znakove
jedne drugima,
ali je takođe moguće i množiti ih! (Uvećati ih za neki broj puta). Vid' ovo:

puts 'blink ' * 4

Ispis:
batting her eyes (...ona trepće očima)

(Šalim se, ono što bi se na ekranu ispisalo je:)


blink blink blink blink

Savršeno je smislen ispis, ako malo razmislite. Uostalom, 7 * 3, znači jednostavno 7+7+7, tako da bi i
'moo'+3 značilo 'moo'+'moo'+'moo'.

12 protiv '12'
Prije nego krenemo dalje, treba se uvjeriti da razlikujemo brojeve i brojke kao znakove. 12 je broj kao
numerička vrijednost, a '12' je string sastavljen od dva znaka – dvije brojke.
Hajde da se malo poigramo ovim razlikama:

puts 12 + 12
puts '12' + '12'
puts '12 + 12'

Ispis:
24
1212
12 + 12

-10-
A šta kažete na ovo:

puts 2 * 5
puts '2' * 5
puts '2 * 5'

Ispis:
10
22222
2 * 5

Ovi su primjeri prilično izravni. Međutim, ako niste pažljivi kako miješate string i brojeve, mogu se javiti
i…

Problemi
Do ovog momenta je vjerovatno bilo stvari koje ste pokušali, pa nisu ispale kako treba. Ukoliko to nije bio
slučaj, evo par primjera:

puts '12' + 12
puts '2' * '5'
#<TypeError: can't convert Fixnum into String>

Hmmm…u ispisu se pojavljuje poruka da je došlo do grješke. Problem je, ustvari, što ne možete sabrati
broj (integer, float) i znakovni niz (string), ili pomnožiti dva znakovna niza (string).
Takve operacije nemaju smisla, kao što nemaju ni ove:

puts 'Betty' + 12
puts 'Fred' * 'John'

Postoji još nekoliko stvarčica na koje morate obratiti pažnju: možete u program napisati 'žaba' * 5, pošto to
znači da će string 'žaba' biti umnožen pet puta. Međutim, ne možete napisati 5 * 'žaba', jer bi to značilo da
je broj pet umnožen žaba puta,...što je baš smiješno [k.p.:...ili kako kod nas kažu: „ne idu babe i žabe“].
Konačno, šta ako želim da moj program napiše „You're swell“? Možemo pokušati ovako:

puts 'You're swell!'

Ali, to baš i neće ispasti dobro; nećemo čak ni pokušavati. Računar je pomislio da smo gotovi s pisanjem
stringa. [k.p.: računar prepoznaje string kao onaj niz znakova koji je zatvoren između dva navoda ' *** '].
(Iz tog je razloga poželjno imati uređivač teksta koji će prikazivati obojenu sintaksu programskog jezika.)
Kako onda da kažemo programskom jeziku kako treba da izgleda naš string? Moramo izbjeći prerano
prekidanje navoda ovako:

puts 'You\'re swell!'

-11-
Ispis:
You're swell!

Kosa crta (nadesno) je rezervisani znak za izbjegavanje/poništavanje prekida navoda stringa. S druge
strane, ako imate kosu crtu i neki drugi znak uz nju, onda su ti znakovi nekad prevedeni u sasvim novi
znak. Jedino što kosa crta poništava su navodi i sama kosa crta. (Ako malo bolje rasmislite, znakovi za
poništavanje uvijek bi morali poništavati sami sebe.) Slijedi nekoliko primjera:

puts 'You\'re swell!' puts 'backslash at the end of a string: \\'


puts 'up\\down'
puts 'up\down'

Ispis:
You're swell!
backslash at the end of a string: \
up\down
up\down

Pošto kosa crta ne poništava „d“ u riječi 'down', nego samu sebe, posljednja dva primjera su identična. Ne
izgledaju isto u kodu, ali na vašem računaru su oni stvarno jednaki.
Ukoliko već sada imate nekih pitanja, nastavite čitati slijedeće poglavlje. Na ovoj stranici nisam mogao
dati baš sve odgovore odjednom.

3. Promjenjive i dodijeljivanje
Do ovog momenta, kad god bismo komandu „puts“ koristili da bi ispisali neki string ili broj, nakon što je
ona izvršena, taj string ili broj bi nestao. Htio sam reći da, ako bismo htjeli ispisati (output) neki string dva
puta, onda bismo ga morali dva puta i otkucati:

puts '...you can say that again...'


puts '...you can say that again...'

Ispis:
...you can say that again...
...you can say that again...

Bilo bi lijepo kad bi to mogli negdje upisati jednom i onda ga i zadržati,...spasiti ga negdje. Pa, naravno da
je to moguće, inače ne bih ni spominjao.

Da bi smjestili neki string u memoriju računara, potrebno je označiti taj cijeli string nekim imenom.
Programeri najčešće ovaj proces opisuju kao dodijeljivanje (assignment), a ime koje će imati taj string
nazivaju varijablom. Samu varijablu možemo označiti bilo kakvim nizom znakova, ali prvi znak mora biti
malo slovo. Da pokušamo ovaj posljednji program napisati još jednom, ali ovaj put string koji smo pisali
iznad, označit ćemo varijablom imena myString (iako samo joj mogao dati i neko sasvim drugo ime, str ili
myOwnLittleString ili henryTheEight).
-12-
myString = '...you can say that again...'
puts myString
puts myString

Ispis:
...you can say that again...
...you can say that again...

Svaki naredni put kad se pozovete na myString, program će umjesto toga koristiti string „...you can say
that again...”. Možete sebi predstaviti varijablu myString kao nešto što upućuje na string „...you can say
that again...”. Evo još nekoliko zanimljivih primjera:

name = 'Patricia Rosanna Jessica Mildred Oppenheimer'


puts 'My name is ' + name + '.'
puts 'Wow! ' + name + ' is a really long name!'

Ispis:
My name is Patricia Rosanna Jessica Mildred Oppenheimer.
Wow! Patricia Rosanna Jessica Mildred Oppenheimer is a really long
name!

Kao što možemo varijabli dodijeliti (assign) neki objekt, tako taj objekat možemo zamijeniti nekim
drugim, unutar iste varijable (reassign). (To i jeste razlog što ih nazivamo promjenjive; ono čemu one teže
može varirati, mijenjati se.)

composer = 'Mozart'
puts composer + ' was "da bomb", in his day.'

composer = 'Beethoven'
puts 'But I prefer ' + composer + ', personally.'

Ispis:
Mozart was "da bomb", in his day.
But I prefer Beethoven, personally.

Naravno, kao varijablu možemo definisati bilo koji objekt, ne samo string:

var = 'just another ' + 'string'


puts var

var = 5 * (1+2)
puts var

Ispis:
-13-
just another string
15

Ustvari, varijable mogu ukazivati na gotovo sve,...osim drugih varijabli. Međutim, šta se desi ako bismo to
ipak pokušali?

var1 = 8
var2 = var1
puts var1
puts var2

puts ''

var1 = 'eight'
puts var1
puts var2

Ispis:
8
8

eight
8

Dakle, prvo smo ukazali var2 na var1, što je toj varijabli dodijelilo objekat koji je definisan prvom
varijablom i dalo rezultat 8. Onda smo dodijelili varijabli var1 drugi objekat (izvršili reassign) „eight“, ali
pošto ustvari var2 nikad nije bila vezana za var1 [k.p.: što znači da se var2 ne mijenja dimanički, ne prati
promjene na var1], njena je vrijednost ostala 8.

Eh sad kad smo naučili nešto o varijablama, brojevima i stringovima, hajde da naučimo i kako sve njih da
pomiješamo u jednom programu!

4. Haj' da malo pomiješamo


Vidjeli smo par različitih objekata (brojevi i slova), a onda definisali i par varijabli da ukažemo na te
objekte; slijedi nam dio u kome ćemo pokušati da sve navedeno lijepo uklopimo u jedan program.

-14-
Moći ćemo primjetiti da, ako želimo da program ispiše 25, kod koji je napisan ispod neće raditi, jer se ne
mogu sabirati brojevi i slova:

var1 = 2
var2 = '5'

puts var1 + var2

Dio je problema i to što računar ne može raspoznati da li želimo dobiti rezultat 7 (2 + 5) ili je 25 rezultat
koji smo željeli. Prije nego budemo u mogućnosti sabrati ova dva objekta, treba nam ili string verzija var1
ili integer verzija var2.

Pretvorbe (konverzije)
Za pretvaranje bilo kojeg objekta u string koristimo dodatak .to_s na kraju neke varijable:
 

var1 = 2
var2 = '5'

puts var1.to_s + var2

Ispis:
25

Slično prethodnom primjeru, dodatak .to_i rezultiraće integer verzijom objekta definisanog tom
varijablom, a prateći istu logiku .to_f će pretvoriti objekat vezan za neku varijablu u float. Pogledajmo sada
pobliže šta ove tri metode mogu, a šta ne mogu učiniti:

var1 = 2
var2 = '5'

puts var1.to_s + var2


puts var1 + var2.to_i

Ispis:
25
7

Primjetit ćete da, čak i nakon što smo dobili string verziju var1 pozivajući .to_s metodu, var1 uvijek
ukazuje na 2, a nikad na '2'. Ukoliko joj ne dodijelimo novu vrijednost/objekat (reassign) (za što nam je
potreban znak '='), var1 će tokom cijelog vremena izvršenja programa ostati 2.

Hajde sada da probamo nekoliko zanimljivih (ali i nekoliko čudnih) primjera pretvorbe:

puts '15'.to_f
puts '99.999'.to_f
-15-
puts '99.999'.to_i
puts ''
puts '5 is my favorite number!'.to_i
puts 'Who asked you about 5 or whatever?'.to_i
puts 'Your momma did.'.to_f
puts ''
puts 'stringy'.to_s
puts 3.to_i

Ispis:
15.0
99.999
99

5
0
0.0

stringy
3

Ispis koji vidimo vjerovatno je proizveo iznenađenje. Prvi primjer je standardno, proizveo 15.0. Nakon
toga smo pretvorili string '99.999' u float, pa u integer. Pretvorba u float je rezultirala očekivano; integer je,
kao i obično, zaokružio vrijednost.

Nadalje, imali smo primjere u kojima je par neuobičajenih stringova pretvoreno u brojeve. Metoda .to_i
ignoriše stvari koje ne može razumjeti, na način da prekida konverziju na mjestu gdje se „nerazumijevanje“
prvi put pojavi i nastavi sve do kraja [k.p. : iz tog razloga u ovom primjeru počinje ignorisati vrijednosti
poslije 5 i nastavlja to do kraja stringa]. Tako je prvi znak pretvoren u 5, a ostali znakovi, obzirom da su
počinjali slovima, ignorisani su u potpunosti,...računar je za njih odabrao samo nule.

Konačno, vidimo naše poslijednje dvije konverzije - nisu nimalo neočekivane.

Još jedan osvrt na „puts“ metodu


Nešto mi je čudna naša omiljena metoda – puts -,...pogledajte samo ovaj primjer:

puts 20
puts 20.to_s
puts '20'

Ispis:
20
20
20

Zašto sve tri metoda daju isti ispis? Dobro, posljednje dvije bi i trebale, obzirom da je 20.to_s jednako '20'.
Ali, šta je s prvim primjerom, brojem 20? Kad smo već kod toga, šta uopšte znači ispisati broj 20 (kao
integer)? Kad napišete dvicu i nulu na komad papira, onda pišete string, a ne vrijednost broja koji bi nastao
kad bi se pridružile te dvije cifre. Broj 20 je broj (vrijednost) prstiju na rukama i nogama, nije to dvica
-16-
praćena nulom.

E pa, otkrit ću vam veliku tajnu o našem prijatelju –puts-. Prije nego ova metoda da bilo kakav ispis
objekta, ona koristi metodu .to_s da bi dobila string verziju objekta koji smo joj stavili u zadatak za ispisati.
Ustvari, ono „S“ koje vidimo na kraju naziva ove metode, znači STRING; tako metoda –puts- znači PUT
STRING.

Za ovu činjenicu se možda trenutno ne mora vezati puno uzbuđenja, ali postoji u Ruby veliki broj različitih
objekata (a naučićete kako da napravite i sami svoje objekte!), te je zato lijepo znati šta će se desiti ako
pokušate „putsovati“ neke malo čudnije objekte kao što su slike vaših nana ili neka omiljena pjesma.
Ali,...to će doći malo kasnije...

U međuvremenu, upoznaćemo se sa par novih metoda, koje će nam dozvoliti da napišemo dosta
zanimljivih programčića...

Metode „gets“ i „chomp“


Rekosmo da –puts- slovi za put string. Siguran sam da ćete lahko pogoditi šta onda –gets- znači. Baš kao
što –puts- svaki put daje ispis stringa, tako –gets- uzima unose u obliku stringa.

Uzima od vas! Ma dobro, od tastature/tipkovnice. Pošto tastatura/tipkovnica „skuplja“ samo znakove


(string), to u slučaju ove metode stvari teku savršeno. Ono što se ustvari dešava je da –gets- ustvari „čuči“ i
čeka sve one znakove koje prospete preko tastature/tipkovnice sve dok ne pritisnete Enter. Hajde da
pokušamo:

puts gets

Ispis:
Is there an echo in here?
Is there an echo in here?

Naravno, u ispisu bi bilo ono što biste vi unijeli nakon što je program pokrenut. Pokrenite program
nekoliko puta, pa upišite različite unose. Sad već možemo krenuti u pisanje programa koji će donijeti malo
više interakcije. U primjeru koji slijedi, upišite svoje ime u program i on će vas pozdraviti:

puts 'Hello there, and what\'s your name?'


name = gets
puts 'Your name is ' + name + '? What a lovely name!'
puts 'Pleased to meet you, ' + name + '. :)'

Hop! Nakon što sam pokrenuo program dobio sam slijedeći ispis:

Hello there, and what's your name?


Chris
Your name is Chris? What a lovely name!
Pleased to meet you, Chris. :)

-17-
Hmmm,...izgleda da, kad bih upisao, C, h, r, i, s, i pritisnuo Enter, -gets- bi zgrabio sva slova koja sam
napisao, pa čak i Enter. Na sreću, postoji metoda kojia se brine za ovakve pojave –chomp-. Ova metoda
izostavlja Enter koji se unese na kraju stringa, odnosno uklanja posljednji znak u stringu, ukoliko se radi o
tzv. separatoru. Hajde da pokušamo preurediti malo prethodni program, sada sa upotrebom metode –
chomp- :

puts 'Hello there, and what\'s your name?'


name = gets.chomp
puts 'Your name is ' + name + '? What a lovely name!'
puts 'Pleased to meet you, ' + name + '. :)'

Ispis:
Hello there, and what's your name?
Chris
Your name is Chris? What a lovely name!
Pleased to meet you, Chris. :)

Tako! To je već bolje! Primjetit ćete da varijabla „name” ukazuje na vezanu metodu gets.chomp, tako da
samoj varijabli ne moramo pridruživati metodu (name.chomp).

Par stvarčica za oprobati


 Napišite program koji traži od osobe da napiše svoje ime, srednje ime, a onda i prezime. Program bi
nakon toga trebao pozdraviti osobu punim imenom i prezimenom. 

 Napišite program koji pita osobu za omiljeni broj. Neka onda vaš program uveća taj broj za jedan i
onda ispiše rezultat predloži osobi kao novi omiljeni broj.

Kad završite s ovim programima, onda možemo krenuti dalje, upoznati se s novim metodama.
Imali smo, do ovog momenta, priliku vidjeti nekoliko metoda, -puts- i –gets- i tako dalje (Nagradno
pitanje: možete li pobrojati sve metode s kojima smo se do sada upoznali? Ima ih deset; a odgovor koje su
– slijedi.), ali nismo puno govorili o tome šta su zapravo metode. Znamo šta one rade, ali ne znam još
uvijek šta one zapravo jesu.

Ustvari to i jeste njihova suština – da rade koješta u programima koje pišemo. Ako u Ruby kao jeziku
objekte (kao što su strings, integers, floats) predstavimo kao imenice, onda su metode vrlo slične
glagolima. Baš kao i u jeziku, ne možete imati glagol, a da nemate određenu imenicu koja će ga izvršiti
(radnju). Na primjer, „kucanje“ nije nešto što se jednostavno dešava; moraćemo imati sat koji to radi. U
jeziku bismo mogli reći da „sat kuca“. Kad bi tu situaciju trebalo prevesti u Ruby, onda bismo naveli u
kodu clock.tick (pretpostavljajući da je clock objekat u Ruby). Programeri bi najvjerovatnije rekli da su
pozvali metodu tick, objekta clock ili . . . „nad objektom clock smo pozvali metodu tick“.

Jeste li odgovorili na nagradno pitanje? Dobro. Siguran sam da ste se sjetili metoda –puts-, -gets- i –
chomp-, iz razloga što smo ih nedavno naučili i ponovili mnogo puta. Garant ste se sjetili i metoda za
pretvorbu -to_i-, -to_s-, -to_f-. Međutim, jeste li uspjeli dokučiti koje su preostale četiri? Ma haj'te, pa to
nije ništa drugo nego naši dobri stari drugovi [+], [-], [*] i [/] – matematički operatori.

Kao što sam već rekao, svaki glagol treba svoju imenicu, pa tako i svaki objekt treba neku metodu. Obično
je vrlo lahko reći koji objekat izvršava metodu; to je onaj koji stoji ispred tačke, kao u našem primjeru
clock.tick, ili na primjer 101.to_s. Ponekad, međutim, nije sve tako očito; kao što je slučaj sa aritmetičkim
-18-
metodama. Kako to i izgleda, napisati 5 + 5 je samo kraći način od pisanja 5.+ 5; na primjer

puts 'hello '.+ 'world'


puts (10.* 9).+ 9

Ispis:
hello world
99

Ovako postaviti aritmetičke metode nije baš najljepše, tako da ih mi nikad nećemo pisati u ovom obliku;
važno je, međutim, razumjeti šta se ustvari događa. (Na mom računaru, došlo mi je i upozorenje
„parenthesize argument(s) for future versions“ – „argumente ubuduće stavi u zagrade“! Iako je pokrenuo
moj program bez problema, računar me je ipak upozorio da ne zna šta sam želio reći ovim kodom i tražio
je od mene da u budućnosti manje koristim zagrade.)

Ovaj nam primjer takođe objašnjava zašto možemo pomnožiti žabu peticom, ali ne možemo peticu
pomnožiti žabom. 'žaba' * 5, govori 'žabi' da učini množenje, a 5 * 'žaba' govori petici da to učini. 'žaba'
zna kako da napravi pet svojih kopija i da ih doda jedne drugima; međutim, petica će ipak imati daleko više
problema praveći 'žaba' svojih kopija i onda ih dodati jedne drugima.

Naravno, ostaje nam štošta objasniti što se metoda –puts- i –gets- tiče. Gdje su njihovi objekti (ispred)? U
jeziku koji govorimo, kao što i sami znate, ponekad možemo izostaviti imenicu; na primjer ako VILLAIN
govori „Umri!“, imenica na koju se ukazuje na onoga na koga se on dere. U Ruby, ako ja kažem - puts 'to
be or not to be' – to ustvari znači –self.puts 'to be or not to be'.– Šta je pa sad self? Self je specijalna
varijabla/promjenjiva koja pokazuje na onaj objekat u kome se nalazite. Još uvijek mi ne znamo šta znači
biti u objektu, ali dok ne spoznamo, treba reći da ćemo uvijek biti u jednom velikom objektu koji je... sam
program koji smo napisali je objekat! Sreća naša, sam program ima svoje metode, kao što su –puts- i –
gets-. Vidi ovo:

iCantBelieveIMadeAVariableNameThisLongJustToPointToA3 = 3
puts iCantBelieveIMadeAVariableNameThisLongJustToPointToA3
self.puts iCantBelieveIMadeAVariableNameThisLongJustToPointToA3

Ispis:
3
3

Ako niste upratili baš sve kako treba, nema veze. Važno iz svega zaključiti da je svaka metoda izvršena od
strane nekog objekta, čak i ako nema tačke ispred objekta. Ukoliko ste shvatili, onda smo spremni da
idemo dalje.

Zanimljive metode namijenjene znakovima (string)


Haj'te da naučimo par zanimljivih metoda koje tretiraju znakove (stringove). Ne morate ih sve učiti
napamet; jednostavno pogledajte ovu stranicu ponovo ako ih zaboravite. Namjera mi je pokazati vam samo
jedan dio onoga što možete učiniti sa znakovima (stringovima). Da budem iskren, ni ja sam ne mogu
upamtiti polovinu metoda koje tretiraju string – ali nema veze, jer postoje izvrsne reference na internetu,
izlistane i sa detaljnim objašnjenjima o njihovoj primjeni. (Uputit ću vas na linkove na kojima ćete naći
liste metoda.) Uistinu, ja i ne želim da znam sve te metode; to nekako dođe kao znati sve riječi iz riječnika.
-19-
Mogu govoriti engleski solidno i bez poznavanja sve do jedne riječi koja je napisana u riječniku...uostalom
to je poenta riječnika...zar ne? Ono što mi u njemu ne znamo je njegova poenta, inače nam ne bi trebao.

Dakle, prva metoda na koju ćemo obratiti pažnju je –reverse-, metoda kojia će nam dati obrnuti redoslijed
znakova u nekom stringu.

var1 = 'stop'
var2 = 'stressed'
var3 = 'Can you pronounce this sentence backwards?'

puts var1.reverse
puts var2.reverse
puts var3.reverse
puts var1
puts var2
puts var3

Ispis:
pots
desserts
?sdrawkcab ecnetnes siht ecnuonorp uoy naC
stop
stressed
Can you pronounce this sentence backwards?

Kao što i sami možete vidjeti, -reverse- ne „izvrće” izvorni string, nego pravi novu „rikverc” verziju istog.
Iz tog razloga var1 ostaje 'stop' čak i nakon što smo pozvali metodu –reverse- nad njom. U nizu metoda je i
metoda –lenght-, koja nam govori koliko znakova (uključujući i razmake, prazne prostore) ima određeni
string:

puts 'What is your full name?'


name = gets.chomp
puts 'Did you know there are ' + name.length + ' characters in your
name, ' + name + '?'

Ispis:
What is your full name?
Christopher David Pine
#<TypeError: can't convert Fixnum into String>

Uh! Uh! Nešto je izgleda krenulo po zlu, a desilo se nakon linije name = gets.chomp... Možete li uočiti gdje
u čemu je problem? Pokušajte otkriti?

Problem je nastao sa metodom –length- : ona kao rezultat daje broj, a ono što mi želimo je string. Ništa
lakše, jednostavno ćemo na čitav izraz nabaciti metodu -to_s-
( i prekrstit' prste [/] držat' fige ):

puts 'What is your full name?'


-20-
name = gets.chomp
puts 'Did you know there are ' + name.length.to_s + ' characters in
your name, ' + name + '?'

Ispis:
What is your full name?
Christopher David Pine
Did you know there are 22 characters in your name, Christopher David
Pine?

Ma nemoj mi reći,…toliko slova u mom imenu,…nisam znao.

Napomena: broj koji je program ispisao je ukupan broj znakova u ovom stringu (name), a ne broj slova
koje moje ime sadrži (eto prebroj'te ih). Mogli bismo napisati i program koji pita ime, srednje ime, prezime
(svako posebno) i onda sabira broj slova svakog od njih...hej! pa zašto to nebiste sami napravili! Hajde, šta
čekate!?

Jeste li? Dobro! Fin programčić, zar ne? Nakon par poglavlja poslije ovoga, bićete i sami začuđeni onim
što ćete znati da programirate.

Postoji takođe i par metoda koje mogu mijenjati kapitalizaciju slova (malo/veliko slovo) koja se nalaze u
nekom od vaših stringova. Metoda –upcase- pretvoriće sva mala slova u velika, a metoda –downcase- sva
velika u mala slova. Nadalje, metoda –swapcase- pravi inverziju stringa, jer slova koja su velika pretvara u
mala, a ona koja su mala pretvara u velika . . . i konačno –capitalize- je metoda slična metodi –downcase-,
s razlikom da na početak stringa stavlja veliko slovo (ako su slova u pitanju).

letters = 'aAbBcCdDeE'
puts letters.upcase
puts letters.downcase
puts letters.swapcase
puts letters.capitalize
puts ' a'.capitalize
puts letters

Ispis:
AABBCCDDEE
aabbccddee
AaBbCcDdEe
Aabbccddee
a
aAbBcCdDeE

To je već standarno, očekivano. Primetićete da u liniji „puts ' a'.capitalize“, metoda –capitalize- samo
pretvara u veliko slovo početni znak, ne prvo slovo [ k.p. : koje je u ovo slučaju razmak ]. Takođe, kao što
sam to i ranije napominjao, uprkos pozivanju raznih metoda, izvorna slova ostaju nepromijenjena. Nemam
namjeru biti dosadan s ponavljanjem, ali je važno da to shvatite. Postoje metode koje mijenjaju objekt koji
ih izvršava, ali mi nismo još došli do njih,...i nećemo tako brzo.

Poslijednja od ovih zanimljivih metoda odnosi se na uređivanje izgleda ispisa. Prva od njih, –center-,
dodaje razmake na početku i kraju stringa da bi ga postavila u sredinu - centrirala.
-21-
Međutim, baš onako kako morate reći metodi –puts- šta želite ispisati, ili metodi [+] šta želite
dodati/sabrati, tako i metodi –center- morate reći kolika širina tog razmaka treba da bude.
Dakle, ako bih htio centrirati stihove iz jedne pjesme, učinio bih slijedeće:

lineWidth = 50
puts( 'Old Mother Hubbard'.center(lineWidth))
puts( 'Sat in her cupboard'.center(lineWidth))
puts( 'Eating her curds an whey,'.center(lineWidth))
puts( 'When along came a spider'.center(lineWidth))
puts( 'Which sat down beside her'.center(lineWidth))
puts('And scared her poor shoe dog away.'.center(lineWidth))

Ispis:
Old Mother Hubbard
Sat in her cupboard
Eating her curds an whey,
When along came a spider
Which sat down beside her
And scared her poor shoe dog away.

Hmmm,…nisam siguran koliko je ova rima pogodna, ali mi je lijeno sad voditi računa o tome.

(Htio sam takođe izravnati i dio linije .center lineWidth, te sam zbog toga stavio razmake ispred stringa.
Mislio sam da će tako ljepše izgledati. Programeri su vrlo često kritični kad je u pitanju šta je „lijepo na
oko“ u programu i često ćete naići na različite stavove. Što više uđete u programiranje, sve više ćete
razvijati neki svoj stil.) Kad smo kod lijenosti, u programiranju ona nije uvijek tako loša. Vidite li, na
primjer, kako sam ja smjestio dužinu linije u varijablu lineWidth? Kad bih kasnije htio učiniti linije širim,
jedino bih morao mijenjati prvu liniju u programu tj. varijablu, a ne svaku vrijednost koja radi centriranje.
Ako bi ovo bio neki veći program, onda bi mi ovaj potez uštedio dosta vremena. Ova vrsta lijenosti u
programiranju je zaista vrlina.

Kako vam se čini centriranje...primjetićete da nije baš onako lijepo kako to izgleda u nekim uređivačima
teksta. Ako je savršeno centriranje ono što želite (i možda malo ljepši font), onda biste jednostavno trebali
koristiti neki uređivač teksta! Ruby je sjajan alat, ali nijedan alat nije pravi alat za baš sve poslove.

Preostale metodu su nam –ljust- i –rjust-, koje pozicioniraju tekst na lijevu ili desnu stranu razvlačeći ga
cijelom širinom linije. Slični su metodi –center-, osim što pomiču string razmacima nalijevo, odnosno
nadesno, respektivno. Hajde da ih vidimo na djelu:

lineWidth = 40
str = '--> text <--'
puts str.ljust lineWidth
puts str.center lineWidth
puts str.rjust lineWidth
puts str.ljust (lineWidth/2) + str.rjust (lineWidth/2)

Ispis:
--> text <--
               --> text <--
                              --> text <--
-22-
     --> text <-- --> text <--

Par stvarčica za oprobati


 Napišite program koji će se zvati „Ljuti šef“. Trebao bi vas pitati šta želite. Šta god da mu
odgovorite, „Ljuti šef“ bi trebao vikati na vas i onda vas otpustiti. Na primjer, ukoliko napišete
„Želim da mi povećate platu.“, on bi vikao: „Želim da mi povećate platu!? To želiš!? E otkaz je ono
što ćeš dobiti!“

Evo jednog zadatka koji će omogućiti da se malo poigrate metodama za formatiranje teksta (-center-,
-ljust- i –rjust-).
 Napišite program koji će napraviti sadržaj ovog tutoriala kao što je prikazano u ispisu:
              Table of Contents
Chapter 1: Numbers page                   1
Chapter 2: Letters page                  72
Chapter 3: Variables page               118

Viša matematika
( Naredni dio ovog poglavlja je potpuno neobavezan. Pretpostavlja se za one koji ga žele čitati da imaju
solidno znanje iz matematike. Ukoliko niste zainteresovani, možete odmah krenuti dalje, na „Kontrola
toka“, bez ikakvih problema. Međutim, bilo bi korisno da makar bacite pogled na dio koji se odnosi na
generisanje brojeva metodom slučajnog uzorka, moglo bi vam nekad zatrebati. )

Postoji približno isti broj metoda za brojeve, kao i za string objekte (iako ih ja ne znam sve napamet, kao i
prethodne). U ovom kratkom dijelu ćemo sagledati ostatak aritmetičkih metoda, vidjeti kako izgleda
generator slučajnih brojeva, Math objekat, sa svojim trigonometrijskim i transcendentalnim metodama.

Više aritmetike
Dvije metode s kojima ćemo započeti ovaj dio su [**] (eksponencija) i [%] (modulus – ostatak nakon
dijeljenja). Dakle, ako želite reći Ruby „pet na kvadrat“, onda biste trebali napisati izraz 5 ** 2. U
proračunima možete takođe koristiti i float objekte za opis eksponenta na koji podižete brojeve, pa ćete u
tom slučaju, ako želite naći kvadratni korijen od pet napisati 5 ** 0.5. Metoda za modulus daje vam
rezultat ostatak nakon dijeljenja dva broja. Na primjer, ako dijelim 7 sa 3, onda kao rezultat dobijem 2 i
ostatak 1. Da vidimo kako to izgleda u programu:

puts 5**2
puts 5**0.5
puts 7/3
puts 7%3
puts 365%7

Ispis:
25
2.23606797749979
2
1
1

Iz poslijednje linije smo naučili da godina ima prilično veliki broj sedmica, plus jedan dan. Ako je vaš
rođendan bio u utorak ove, slijedeće godine bi trebao pasti u srijedu. Sa metodom [%] mogu se takođe
-23-
koristiti i float objekti. U suštini, radi na jedini mogući osjetljivi način za njega,...ali taj ću dio ostaviti
vama, da se malo igrate.

Pomenut ću samo još jednu metodu prije nego pređemo na generator slučajnog broja: -abs-. Ta metoda
jednostavno računa apsolutnu vrijednost broja:

puts((5-2).abs)
puts((2-5).abs)

Ispis:
3
3

Slučajni brojevi
Ruby ima prilično zgodan generator slučajnog broja (random). Metoda koja pomaže da se dobije neki
slučajni broj je –rand-. Ako pozovete tu metodu bez specifikacije, onda ćete dobiti slučajni float koji će
vrijednosno biti smješten ili jednak od 0.0 do 1.0. Međutim, ako metodi –rand- pridružite neki integer
(recimo 5), daće vam kao rezultat integer veći ili jednak nuli, a manji od petice (dakle, pet mogućih
brojeva, od 0 do 4).

Pogledajmo sada –rand- u akciji. [k.p. Ukoliko na originalnom tutorialu učitate ovu stranicu ponovo,
brojevi će se promijeniti svaki put kad ih učitate.] (...pa znali ste da sam sve ove programe, osim što sam ih
napisao, pokrenuo/izvršavao na računaru, zar ne?)

puts rand
puts rand
puts rand
puts(rand(100))
puts(rand(100))
puts(rand(100))
puts(rand(1))
puts(rand(1))
puts(rand(1))
puts(rand(99999999999999999999999999999999999999999999999999999999999))

puts('The weatherman said there is a '+rand(101).to_s+'% chance of


rain,')
puts('but you can never trust a weatherman.')

Ispis:
0.593474785354615
0.660763674309727
0.422511416882603
78
27
38
0
0
0
91506176963496451620599165354140390470043157669278537593542
-24-
The weatherman said there is a 100% chance of rain, but you can never
trust a weatherman.

Zamijetit ćete da sam koristio rand(101) da bih dobio za rezultat brojeve između 0 i 100; ali i da će za
rand(1) rezultat uvijek biti 0. Nerazumijevanje vrijednosti koje bi se mogle očekivati kao rezultat je jedna
od najvećih grješaka koje ljudi prave sa metodom –rand-, pa čak i profesionalni programeri; na nekim
proizvodima koji su plasirani na tržište mogu se uočiti takve grješke. Ima sam čak jednom neki CD player,
pa kad bih stavio muziku na „random play“ modus, mogao sam preslušati sve pjesme osim posljednje...
(pitam se šta bi se desilo da sam imao CD na kome se nalazila samo jedna pjesma?)

Ponekad će biti potrebno da –rand- ispiše iste slučajne brojeve istim redoslijedom na sva različita izvršenja
programa. (Na primjer, jednom sam korisito slučajne brojeve da generišem slučajno/spontano mapu za
računarsku igru. Ako bih naišao na mapu koja bi mi odgovarala, htio bih je igrati ponovo, ili bih je mogao
poslati prijatelju.) Da bismo postigli navedeno, treba postaviti SEED, što se može učiniti deriviranom
metodom –srand-. 'vako to se radi:

srand 1776
puts(rand(100))
puts(rand(100))
puts(rand(100))
puts(rand(100))
puts(rand(100))
puts ''
srand 1776
puts(rand(100))
puts(rand(100))
puts(rand(100))
puts(rand(100))
puts(rand(100))

Ispis:
24
35
36
58
70

24
35
36
58
70

Svaki put kad ga SEEDATE istim brojem, program će dati isti rezultat. Ukoliko želite dobiti drukčije
brojeve (što bi se desilo da uopšte nismo koristili –srand-) onda jednostavno pozovite srand 0. Ovakav
SEED koristi stvarno čudan broj, koji između ostalo može dati i trenutno vrijeme na vašim računarima, do
u milisekundu.

„Math“ objekat
Konačno, da vidimo šta je taj „Math“ objekat. Možda je najbolje da odmah uskočim u primjer:
-25-
puts(Math::PI)
puts(Math::E)
puts(Math.cos(Math::PI/3))
puts(Math.tan(Math::PI/4))
puts(Math.log(Math::E**2))
puts((1 + Math.sqrt(5))/2)

Ispis:
3.14159265358979
2.71828182845905
0.5
1.0
2.0
1.61803398874989

Prva stvar koju ćete vjerovatno primjetiti je [::] – dupla dvotačka. Objasniti „scope operator” (što je upravo
njegov opis) stvarno je izvan, hm…domašaja ovog tutoriala. Nemam namjeru vrijeđati. Kunem se. Ne
treba posebno naglašavati da Math::PI daje upravo onaj rezultat koji smo i očekivali.

Kao što vidite, Math objekat radi one stvari koje bismo očekivali od nekog dobrog naučnog
kalkulatora/digitrona. Kao i uvijek, float je uglavnom rezultat operacija koje tretira ovaj objekat. Hajde
sada, da „tečemo“!

6. Kontrola toka
Aaa, kontrola toka. Ovdje „sve dolazi na svoje“. Iako je ovo poglavlje nešto kraće i lakše od prethodnog,
poglavlja o metodama, vidjet ćemo da će otvoriti čitav svijet mogućnosti u programiranju. Nakon ovog
poglavlja, bićete zaista u stanju napisati interaktivan program; programi koje smo pisali prije ovog
poglavlja „govorili“ različite stvari na osnovu onoga što smo unijeli putem tastature/tipkovnice, ali nakon
ovog poglavlja ćete biti u stanju napisati i one programe koji će „uraditi“ različite stvari. No, prije nego
dođemo do toga, moraćemo naučiti da pravimo razliku među objektima u našim programima. Trebaće
nam...

Metode poređenja
Hajde da „protutnjimo“ kroz ovaj podnaslov, kako bi smo mogli što prije preći na „Grananje“, podnaslov
gdje ćemo naći sve ono što je zanimljivo. Dakle, da bi utvrdili da li jedan objekat veći ili manji od drugog,
koristimo metode [>] i [<], kao u slijedećem primjeru:

-26-
puts 1 > 2
puts 1 < 2

Ispis:
false
true

Kako vidite, tu nije bilo nikakvih problema. Slično prethodnom primjeru, saznaćemo da li je neki objekat
veći ili jednak, odnosno manji ili jednak drugom koristeći metode [>=] i [<=]

puts 5 >= 5
puts 5 <= 4

Ispis:
true
false

Konačno, želimo li saznati da li su dva objekta jednaka ili ne, koristeći metode [==] (što znači „jesu li ovi
objekti jednaki?”) i [!=] (što znači „jesu li ovi objekti različiti?”). Da ne bi došlo do zabune, važno je
napomenuti da metoda [=] služi za dodijeljivanje vrijednosti varijabli, a metoda [==] za prethodno
navedenu svrhu. Ove dvije metode se ne smiju izjednačiti.

puts 1 == 1
puts 2 != 1

Ispis:
true
true

Moguće je, naravno, uporediti i string objekte (tekst). Kriterij za poređenje znakova je njihov
leksikografski red, što praktično znači njihov red u riječniku – u abecedi. Imenica (u engleskom jeziku)
'cat' dolazi prije imenice 'dog' i u riječniku, pa tako će biti i u ovom primjeru:

puts 'cat' < 'dog'

Ispis:
true

Postoji jedna mala caka: način na koji računari obično funkcionišu jer da poredaju prvo velika slova, pa tek
onda mala. (Tako se redaju znakovi i u fontovima [font fajlovima]: prvo dolaze sva velika slova, a onda
mala.) To bi značilo da riječ 'Zoo' dolazi prije 'ant', pa ako želite upitati koja riječ dođe prije u riječniku,
pobrinite se da koristite ili samo mala, ili samo velika slova u riječi,...ili da ih „provučete“ kroz metodu
-capitalize- [k.p.: sjećate li se metoda koje se bave kapitalizacijom?].

-27-
Poslijednja napomena prije nego pređemo na „Grananje“: Rezultati koje nam daju metode poređenja 'true'
[tačno] i 'false' [netačno] nisu string tip objekta, nisu obični tekst,...to su specijalni objekti true i false. [k.p.:
logički tip podatka, nazvan još i Boolean.] (Naravno, ako bi smo upotrijebili true.to_s, onda bi rezultat bio
'istinski' istinit, jer bi nam -puts- dao string kao rezultat. 'true' i 'false' redovno se pojavljuju u svim
programima kod kojih nailazimo na...

Grananje
Grananje je jako jednostavan, ali jako moćan koncept u programiranju. Ustvari, tako je jednostavan da se
kladim da ga uopšte ne moram posebno objašnjavati; jednostavno ću vam pokazati na primjeru:

puts 'Hello, what\'s your name?'


name = gets.chomp
puts 'Hello, ' + name + '.'
if name == 'Chris'
puts 'What a lovely name!'
end

Ispis:
Hello, what's your name?
Chris
Hello, Chris.
What a lovely name!

Ali, ako upišemo neko drugo ime…

Ispis:
Hello, what's your name?
Chewbacca
Hello, Chewbacca.

To bi bilo grananje. Ako je tačno [true] ono što dolazi poslije uslova [if], onda će biti izvršen kod između
[if] i [end], a ako poslije uslova odgovor bude netačan [false] onda taj dio koda neće biti izvršen.
Jednostavno.

Uvrstio sam kod između [if] i [end] jer sam mislio da će tako biti lakše pratiti grananje. Skoro svi
programeri to rade, bez obzira koji programski jezik koriste. Možda vam se sada čini da to i nije od velike
pomoći, međutim, kad se stvari zakomplikuju, vidjet ćete kako je velika razlika.

Često se desi da bismo željeli da program učini jedno, ako je uslov zadovoljen [true] ili drugo ako nije
[false]. Za tu svrhu imamo [else]:

puts 'I am a fortune-teller. Tell me your name:'


name = gets.chomp
if name == 'Chris'
puts 'I see great things in your future.'
else
puts 'Your future is... Oh my! Look at the time!'
puts 'I really have to go, sorry!'
-28-
end

Ispis:
I am a fortune-teller. Tell me your name:
Chris
I see great things in your future.

Ako pokušamo s drukčijim imenom...

Ispis:
I am a fortune-teller. Tell me your name:
Ringo
Your future is... Oh my! Look at the time!
I really have to go, sorry!

Grananje je neka vrsta odabira puta u kodu: dali da krenemo putanjom onih kod kojih je name == 'Chris',
ili da odaberemo neku drugu putanju [else].

Baš kao što postoje grančice da grani jednog drveta, tako i grane u programiranju imaju grane koje se
nalaze unutar njih samih:

puts 'Hello, and welcome to 7th grade English.'


puts 'My name is Mrs. Gabbard. And your name is...?'
name = gets.chomp
if name == name.capitalize
puts 'Please take a seat, ' + name + '.'
else
puts name + '? You mean ' + name.capitalize + ', right?'
puts 'Don\'t you even know how to spell your name??'
reply = gets.chomp
if reply.downcase == 'yes'
puts 'Hmmph! Well, sit down!'
else
puts 'GET OUT!!!'
end
end

Ispis:
Hello, and welcome to 7th grade English.
My name is Mrs. Gabbard. And your name is...?
chris
chris? You mean Chris, right?
Don't you even know how to spell your name??
yes
Hmmph! Well, sit down!

Dobro, ako ispravim ono u čemu sam pogriješio...

-29-
Ispis:
Hello, and welcome to 7th grade English.
My name is Mrs. Gabbard. And your name is...?
Chris
Please take a seat, Chris.

Ponekad će možda biti teško razaznati na koje mjesto postaviti sve te if, else, end. Ja sebi olakšam tako što
odmah napišem [if], a ispod njega [end]. Dakle kad sam pisao pređašnji program, isprva je izgledao ovako:

puts 'Hello, and welcome to 7th grade English.'


puts 'My name is Mrs. Gabbard. And your name is...?'
name = gets.chomp

if name == name.capitalize
else
end

Nakon toga sam dodao komentare, dijelove koda u programu koje će računar ignorisati prilikom
izvršavanja programa:

puts 'Hello, and welcome to 7th grade English.'


puts 'My name is Mrs. Gabbard. And your name is...?'
name = gets.chomp

if name == name.capitalize
# Gospođa je u ovom slučaju pristojna.
else
# ...a u ovom izgubi živce.
end

Sve što dođe poslije znaka # smatra se komentarom (osim, naravno, ako taj znak ne pišete unutar stringa).
Nakon toga sam komentare zamijenio pravim kodom. Neki vole ostaviti komentare, ali ja, kako
napredujem u Ruby, sve manje ih koristim. Da budem iskren, smatram da većinom odvlače pažnju od
pravog koda. Stvar je ličnog izbora, hoćete li koristiti komantare,...sami ćete pronaći svoj stil. Onda, moj
slijedeći korak u pisanju ovog koda bio je:

puts 'Hello, and welcome to 7th grade English.'


puts 'My name is Mrs. Gabbard. And your name is...?'
name = gets.chomp

if name == name.capitalize
puts 'Please take a seat, ' + name + '.'
else
puts name + '? You mean ' + name.capitalize + ', right?'
puts 'Don\'t you even know how to spell your name??'
reply = gets.chomp

-30-
if reply.downcase == 'yes'
else
end
end

Nanovo sam napisao [if], [else] i [end] odmah, u isto vrijeme. To mi stvarno pomaže da se bolje snalazim u
kodu, jer se mogu fokusirati na manje dijelove koda ispunjavajući dio koji se nalazi između [if] i [end].
Druga pogodnost ovog pristupa je što računar može razumjeti program u svakoj njegovoj fazi. Svaku od
verzija programa, iako nedovršenu, računar će moći da izvrši – neće biti grješaka. Dakle, još uvijek
nedovršeni, ali programi koji ipak funkcionišu. Na taj način sam mogao ujedno i testirati program, dok ga
pišem, što mi je pomoglo da izađem na kraj sa stvarima na koja je još trebalo poraditi. Kad je testiranje bilo
završeno, onda sam znao da je posao dobro odrađen.

Slijedi nekoliko caka koje će vam pomoći s grananjem, ali i nekim drugim tipovima kontrole toka:

Kruženje
Često će biti potrebno narediti računaru da ponovi neki postupak nekoliko puta, što je nešto u čemu bi
računari trebali da su stvari dobri.

Kad kažete računaru da ponavlja nešto, morate se pobrinuti i da mu kažete kad da stane. Njima nikad ne
dosadi da to rade, tako da, ako im ne kažete da stanu, oni neće prestati. Da bismo se pobrinuli da se ovo ne
desi, naređujemo računaru da ponavalja određenu metodu sve dok se ispunjava određeni uslov, dok je on
[true] ili jednak zadanoj vrijednosti. Ovako bi to otprilike izgledalo:

command = ''

while command != 'bye'


puts command
command = gets.chomp
end

puts 'Come again soon!'

Ispis:

Hello?
Hello?
Hi!
Hi!
Very nice to meet you.
Very nice to meet you.
Oh... how sweet!
Oh... how sweet!
bye
Come again soon!

To bi, dakle, bilo kruženje. (Vjerovatno ste primjetili prazan string na početku ispisa; rezultat je to koji daje
prvi –puts-, prije prvog -gets-. Kako biste preuredili kod, pa da se riješimo prve linije. Pokušajte! Nije li
rezultat bio isti kao i kod originalnog programa (iznad), samo što nije sadržavao prazne linije u ispisu?)

-31-
Kružne petlje, siguran sam da i sami možete zamisliti, dozvoliće da se uradi dosta zanimljivih stvari.
Međutim, mogu prouzrokovati dosta problema, napravite li grješku u kodu. Šta ako se desi da grješka u
kodu uzrokuje beskonačno ponavljanje? Ako mislite da se ovo desilo, pokušajte kombinaciju tipki CTRL +
C.

Prije nego se nastavimo igrati sa kružnim petljama, hajde da naučimo par stvarčica koje će nam olakšati
posao.

Malo logike...
Hajde da pogledamo prvi program u “Grananju” ponovo. Šta da je moja žena došla kući, vudjela program,
isprobala ga i nije joj rekao kako divno ime ima? Ja baš i ne bih htio povrijediti njena osjećanja (ili spavati
tu noć na kauču), pa sam kod ispravio na slijedeće:

puts 'Hello, what\'s your name?'


name = gets.chomp
puts 'Hello, ' + name + '.'
if name == 'Chris'
puts 'What a lovely name!'
else
if name == 'Katy'
puts 'What a lovely name!'
end
end

Ispis:
Hello, what's your name?
Katy
Hello, Katy.
What a lovely name!

Izgleda da radi, bez problema,…ali nije baš najljepši program. Zašto ne? Pa, najveće pravilo koje sam
naučio u programiranju je NP pravilo: Nemoj ponavljati. Vjerovatno bi se dala knjiga napisati o tome zašto
je to jako dobro pravilo. U našem slučaju, linija puts 'What a lovely name!' je ona koja se ponavalja. Zašto
je to tako strašno? Šta das sam napravio grješku u pisanju, kad sam ponovo pisao istu liniju koda? Šta ako
sam želio ‘lovely’ prepraviti u neki drugi atribut, u oba primjera/linije? Sjećate li se da sam rekao da sam
lijen? U suštini, htio sam da program kaže kako su imena lijepa samo kad putem metode –get- dobije unos
'Chris' i 'Katy'...ukratko, samo u slučaju da dobije jedno od ta dva imena, trebalo bi uraditi istu stvar:

puts 'Hello, what\'s your name?'


name = gets.chomp
puts 'Hello, ' + name + '.'
if (name == 'Chris' or name == 'Katy')
puts 'What a lovely name!'
end

Ispis:
Hello, what's your name?
Katy
Hello, Katy.
What a lovely name!
-32-
Tako je već mnogo bolje. Da bih ostvario ono što sam naveo, koristio sam logički operator [or] (ili). Ostali
logički operatori koje ćemo koristiti su [and] (i) i [not] (ne). Uvijek je dobar potez koristiti zagrade kada
radimo sa ovim operatorima. Pogledajmo kako oni rade:

iAmChris = true
iAmPurple = false
iLikeFood = true
iEatRocks = false

puts (iAmChris and iLikeFood)


puts (iLikeFood and iEatRocks)
puts (iAmPurple and iLikeFood)
puts (iAmPurple and iEatRocks)
puts
puts (iAmChris or iLikeFood)
puts (iLikeFood or iEatRocks)
puts (iAmPurple or iLikeFood)
puts (iAmPurple or iEatRocks)
puts
puts (not iAmPurple)
puts (not iAmChris )

Ispis:
true
false
false
false

true
true
true
false

true
false

Samo jedan od ovih primjera bi vas mogao malo zbuniti. U govoru, dok s nekim pričamo, koristeći „ili“
želimo reći da od dvije opcije biramo samo jednu, ali ne oboje. Naprimjer, majka vas može upitati šta želite
za dezert, pitu ili kolač. Time nije rekla da možete dobiti oboje! Računar, s druge strane, koristi „ili“ [or]
kao logički operator koji znači da ili jedna ili druga vrijednost može odgovarati uslovu, pa da se on ispuni.
(Još jedan način da se kaže „ako je makar jedan od ovih uslova tačan [true].“) Zato računari i jesu
zanimljiviji od majki.

Par stvarčica za oprobati


 „99 bottles of beer on the wall...“ Napišite program koji će ispisati tekst ove stare, dobre pjesme.
 Napišite program pod imenom „Gluha baba“. Šta god da joj kažete (otipkate), ona će odgovoriti sa
velikim HA?! MALO GLASNIJE!, osim ako joj tekst unesete velikim slovima. Ukoliko vičete,
onda će vas i čuti (ili bar tako ona misli) i odgovoriti vam NISAM! NISAM, SINKO JOŠ OD 1938!
Da bi vaš program bio zaista uvjerljiv, neka umjesto „sinko“ svaki put izgovori neko drugo ime; a
-33-
možda da tome i dodate da umjesto 1938 navede neku slučajno generisanu godinu (random) između
1938 i 1950 (Ovaj dio je opcionalan, a biće dobro da pročitate poglavlje o metodama, da se malo
podsjetite o generisanju slučajnih brojeva u Ruby). Na kraju, nećete se moći otarasiti babe, dok joj
ne kažete ĆAO, BABA!
Caka #1: nemojte zaboraviti metodu –chomp-, jer „ĆAO, BABA!“ sa Enterom i bez njega, nije isto!
Caka #2: pokušajte otkriti koji dio programa se treba ponavljati; taj dio bi trebao biti uvršen u kružnu
petlju koja počinje sa [while].
 Proširite svoj program „Gluha baba“: Šta ako baba ne želi da idete? Kad joj viknete ĆAO, BABA!,
ona će se praviti da vas ne čuje. Promijenite pređašnji program tako da joj tri puta morate reći ĆAO,
BABA! zaredom. Pobrinite se da dobro da testirate vaš program: ukoliko joj ne kažete ĆAO,
BABA! tri puta zaredom, ona će i dalje htjeti da razgovara s vama.
 „Protekle prijestupne godine“. Napišite program koji će pitati početnu i krajnju godinu, te na
osnovu toga izračunati koliko prijestupnih godina ima između tog roka, uključujući i njih same.
Prijestupne su godine dijeljive sa 4 (kao 1984 ili 2004). Međutim, godine dijeljive sa 100 nisu
prijestupne osim ako su u isto vrijeme dijeljive i sa 400 (kao 1600 i 2000, koje su bile prijestupne).
(Da, prilično je zapetljano.)

Kad završite s programima, napravite malu pauzu! Stvarno smo već dosta toga naučili. Čestitke! Jeste li
iznenađeni koliko postoji stvari koje možete narediti računaru da uradi? Par poglavlja dalje i bićete u stanju
programirati sve što poželite. Ozbiljno! Pogledajte samo koliko stvari možete sad kad ste naučili grananje i
kruženje, a ranije bez toga niste mogli.

Na redu su nam nove vrste objekata, oni koje bilježe liste nekih drugih objekata: Nizovi.

7. Nizovi i upravljači
Hajde da napišemo program koji traži od nas da upišemo onoliko riječi koliko želimo (jednu riječ po liniji,
sve dok ne pritisnemo Enter u praznoj liniji), a nakon toga ponavlja te riječi po abecednom redu. OK?

Pa...prvo ćemo,...hm...ovaj... moglo bi se...mmm...

Znate šta, mislim da to ne možemo napraviti. Treba nam nešto što će pohraniti nepoznat broj riječi i držati
ih sve na broju, da se ne bi pomiješale sa drugim varijablama/promjenjivim. Trebaće nam dakle nizovi.

Najjednostavnije rečeno, nizovi predstavljaju liste na vašem računaru. Svako mjesto u nizu ponaša se kao
varijabla: možete vidjeti na kojem mjestu se nalazi određeni objekat i možete takođe ukazati i na neki drugi
objekat unutar tog niza. Da pogledamo kako izgledaju neki nizovi:

[]
[5]
['Hello', 'Goodbye']
-34-
flavor = 'vanilla'      # Ovo, naravno, nije niz…
[89.9, flavor, [true, false]]      # ...ali ovo jeste.

Dakle, prvo imamo prazan niz, onda niz koji sadrži samo jedan broj, nakon toga niz koji sadrži dvije riječi
(string). Poslije toga dolazi jednostavno dodijeljivanje varijable; onda niz koji sadrži tri objekta, od kojih je
poslijednji i sam niz [true, false]. Upamtite, varijable nisu objekti, tako da naš poslijednji niz sadrži
slijedeće objekte: float, string i niz [array]. Čak i ako bismo podesili 'flavour' da ukazuje na nešto drugo, to
ne bi promijenilo niz.

Da bismo mogli naći određeni objekt u nizu, sva popunjena mjesta u niz su brojčano indeksirana.
Programeri (kao i većina matematičara) počinju brojati od nule, tako da prvo mjesto (slot) u kome je
smješten neki objekat ima 0 u indeksu. Evo kako bismo uspostavili vezu brojčanog indeksa i objekata u
nizu:

names = ['Ada', 'Belle', 'Chris']

puts names
puts names[0]
puts names[1]
puts names[2]
puts names[3]    # Ovaj indeks je nepostojeći.

Ispis:
Ada
Belle
Chris
Ada
Belle
Chris
nil

Dakle, možemo vidjeti da –puts names- ispisuje svako od imena u nizu names. Nakon toga koristimo –
puts names[0]- da bismo dobili ispis objekta koji je na prvom mjestu u nizu, -puts names[1]- za ispis
slijedećeg,... Siguran sam da bi s početka moglo zvučati zbunjujuće, ali navikne se čovjek, brzo.
Jednostavno se morate prilagoditi mišljenju da brojanje počinje od nule, a prestati misliti da riječ prvi
odgovara tom broju. Na ruci postoji pet prstiju, a njihovi su brojevi 0,1,2,3 i 4. Na kraju, shvatit ćete kako
su indeksirani objekti u nizu kad počnete za redati objekt od „nultog“. Da , nulti je prava riječ; postoji;
pitajte bilo kojeg programera ili matematičara.

Konačno, pokušali smo ispisati –puts names[3]-, samo da bi vidjeli šta se desi. Očekivali ste grješku?
Ponekad, kad postavite neko pitanje, a ono nema smisla (bar ne za računar) onda u ispisu dobijete grješku.
S druge strane, ponekad možete postaviti pitanje a da njegov odgovor bude „ništa“ [nil]. Šta je na mjestu
koje nosi indeks [3]? Ništa. „Nil“ je način na koji nam Ruby poručuje da se na indeksu [3] našeg niza ne
nalazi ništa,...a „nil“ se tretira kao objekat koji znači nepostojanje bilo kakvog objekta.

Ako vas plaši svo ovo nabrajanje, koje mjesto koji objekat zauzima u nizovima, ne bojte se! Često ih
možemo izbjeći koristeći neke od metoda karakteristične za nizove, kao naprimjer:

Metoda „each“
-35-
-each- nam dozvoljava da učinimo nešto (bilo šta da želimo) sa svakim pojedinim bojektom sadržanom u
nekom nizu. Tako dakle, ako želimo reći nešto lijepo o svakom od jezika u nizu, onda ćemo napisati
slijedeći kod:

languages = ['English', 'German', 'Ruby']

languages.each do |lang|
puts 'I love ' + lang + '!'
puts 'Don\'t you?'
end

puts 'And let\'s hear it for C++!'


puts '...'

Ispis:
I love English!
Don't you?
I love German!
Don't you?
I love Ruby!
Don't you?
And let's hear it for C++!
...

Šta se upravo desilo? Uspjeli smo proći kroz sve objekte u nizu, a nismo morali da nabrajamo svaki
pojedinačno, koristeći indeksirane brojeve za poziciju u nizu. Prevedeno na jezik početnika, pređašnji
program razumijeva to kao naredbu: „za svaki objekat u nizu languages napravi varijablu lang koja će
ukazati na objekat unutar niza i onda učini sve što ti kažem dok ne dođeš do kraja niza, odnosno kraja
metode“. (Jedna mala opaska: među brojnim programskim jezicima, postoji i jedan zvani C++, kojega je
daleko teže naučiti od Ruby; obično C++ program ima mnogo više linija nego bi imao neki program sa
istom svrhom napisan u Ruby.)

Možda se zapitate, „Ova metoda je slična kružnoj petlji [loop], koji smo naučili u poglavlju prije ovoga.“
Da, slična jeste. Međutim, jedna vrlo važna razlika je da je –each- samo to: metoda; dok while i end nisu
metode (kao što to nisu do, if, else). Ove rezervisane riječi su dijelovi Ruby kao programskog jezika, baš
kao što su to znakovi =, ili zagrade; ne neki način kao znakovi interpunkcije u jeziku.

Ali ne i –each-; -each- je metoda namijenjena nizovima. Metode koje služe kao kruženje (kružne petlje),
kao što je –each-, često se nazivaju upravljači ili ITERATORI.

Jedna fina stvar kod ITERATORA je da su uvijek praćeni riječima do . . . end. Druge, poput while i if,
nikad nisu trebale do u svojoj bilizini; koristimo ih samo kod ITERATORA.

Slijedi još jedan mali primjer ITERATORA, ali ne kao metode namijenjene nizu nego kao ...integer
metode!

3.times do
puts 'Hip-Hip-Hooray!'
end

-36-
Ispis:
Hip-Hip-Hooray!
Hip-Hip-Hooray!
Hip-Hip-Hooray!

Još nekoliko metoda namijenjenih nizovima


Dakle, naučili smo metodu –each-, međutim, ima još dosta njih koje su namijenjene nizovima, gotovo
jednak broj koliko ih postoji i za string objekte! Ustvari, neke od njih (kao što su –length-, -reverse-, -+- i
-*-) rade isto onako kako bi radile i sa stringovima, osim što rade na pozicijama objekata u stringu, a ne na
znakovima koje sadrži string.  Druge metode, kao što su –last- i –join- specifične su samo za nizove. Ima i
onih kao što su –push- i -pop-, koje zapravo mogu izmijeniti niz. Ono što sam ranije rekao za pamćenje
metoda za stringove, važi i za metode koje su posvećene nizovima; ne morate ih pamtiti sve dok vam je
poznato gdje ćete ih pronaći (ovdje).

Prvo ćemo pogledati -.to_s- i –join- metode. –join- metoda radi slično metodi -.to_s- , a razlika je što
dodaje string između dva objekta u nizu. Da pogledamo:

foods = ['artichoke', 'brioche', 'caramel']

puts foods
puts
puts foods.to_s
puts
puts foods.join(', ')
puts
puts foods.join(' :) ') + ' 8)'

200.times do
puts []
end

Ispis:
artichoke
brioche
caramel

artichokebriochecaramel

artichoke, brioche, caramel

artichoke :) brioche :) caramel 8)

Kao što možete vidjeti, -puts- tretira nizove različito od ostalih objekata: jednostavno poziva put string za
svaki od objekata u nizu. Iz tog razlova „putsovanje“ praznog niza 200 puta neće dati nikakav rezultat; niz
ne ukazuje na bilo kakve objekte, pa tako ni za metodu –puts- nema ničega što bi ispisala. (Uraditi ništa
200 puta jednačko je ničemu.) Pokušajte „putsovati“ neki niz koji sadrži nizove kao objekte; da li je
rezultat ono što ste očekivali?

Takođe, da li ste primjetili da sam ispred –puts- stavio prazan string svaki put kad bih htio dobiti novi
prazan red u ispisu?

-37-
Da sada pređemo na metode –push-, -pop- i –last-. Metode –push- i –pop- su opozitne, slično opoziciji
koju predstavljaju – i +. Metoda –push- dodaje objekat na kraj niza, a metoda –pop- uklanja objekat sa
poslijednjeg mjesta u nizu (usput govoreći koji je to objekat). Metoda –last- slična je metodi –pop- utoliko
što govori koji se objekat nalazi na poslijednjem mjestu u nizu, ali ne vrši nad njim nikakvu operaciju. Što
je važno, metode –push- i -pop- ustvari vrše izmjene na nizu:

favorites = []
favorites.push 'raindrops on roses'
favorites.push 'whiskey on kittens'

puts favorites[0]
puts favorites.last
puts favorites.length

puts favorites.pop
puts favorites
puts favorites.length

Ispis:
raindrops on roses
whiskey on kittens
2
whiskey on kittens
raindrops on roses
1

Par stvarčica za oprobati


 Napišite program o kome smo pričali na početku. (Caka: postoji jedna divna metoda za sortiranje
objekata u nizu: -sort- Iskoristite ga!)
 Pokušajte isti program napisati bez korištenja metode –sort-. Dobar dio programiranja je ustvari
riješavanje problema, dajte se onda u vježbu!
 Napišite ponovo program „SADRŽAJ“ (iz poglavlja o metodama). Počnite program s nizom koji će
sadržavati sve naslove koje sadržaj treba da ima (ime poglavlja, broj strane,...). Onda ispišite
informacije iz niza u divno formatiran „SADRŽAJ“.

Mnogo je metoda koje smo do sada naučili. Sad je vrijeme da naučimo i sami praviti metode. Naše vlastite.

8. Pisanje vlastitih metoda


Kako smo mogli vidjeti, kružne petlje i upravljači (iteratori) dozvoljavaju nam da određene dijelove koda,
odnosno programa, ponavaljamo željeni broj puta. Međutim, ponekad će biti potrebno da uradimo istu
stvar nekoliko puta, ali na različitim mjestima unutar programa. Naprimjer: recimo da pišemo upitnik za
studenta psihologije. Prema onome što sam dobio od studenata psihologije, upitnik bi vjerovatno izgledao
ovako:

puts 'Hello, and thank you for taking the time to'
puts 'help me with this experiment. My experiment'
puts 'has to do with the way people feel about'
-38-
puts 'Mexican food. Just think about Mexican food'
puts 'and try to answer every question honestly,'
puts 'with either a "yes" or a "no". My experiment'
puts 'has nothing to do with bed-wetting.'
puts

# Postavljamo pitanja, ali zanemarujemo odgovore na njih.

goodAnswer = false
while (not goodAnswer)
puts 'Do you like eating tacos?'
answer = gets.chomp.downcase
if (answer == 'yes' or answer == 'no')
goodAnswer = true
else
puts 'Please answer "yes" or "no".'
end
end

goodAnswer = false
while (not goodAnswer)
puts 'Do you like eating burritos?'
answer = gets.chomp.downcase
if (answer == 'yes' or answer == 'no')
goodAnswer = true
else
puts 'Please answer "yes" or "no".'
end
end

# Međutim na „ovaj“ odgovor ćemo obratiti pažnju.

goodAnswer = false
while (not goodAnswer)
puts 'Do you wet the bed?'
answer = gets.chomp.downcase
if (answer == 'yes' or answer == 'no')
goodAnswer = true
if answer == 'yes'
wetsBed = true
else
wetsBed = false
end
else
puts 'Please answer "yes" or "no".'
end
end

goodAnswer = false
while (not goodAnswer)
puts 'Do you like eating chimichangas?'
answer = gets.chomp.downcase
if (answer == 'yes' or answer == 'no')
goodAnswer = true
else

-39-
puts 'Please answer "yes" or "no".'
end
end

puts 'Just a few more questions...'

goodAnswer = false
while (not goodAnswer)
puts 'Do you like eating sopapillas?'
answer = gets.chomp.downcase
if (answer == 'yes' or answer == 'no')
goodAnswer = true
else
puts 'Please answer "yes" or "no".'
end
end

# Postavite još neka pitanja, ako želite, na isti način.

puts
puts 'DEBRIEFING:'
puts 'Thank you for taking the time to help with'
puts 'this experiment. In fact, this experiment'
puts 'has nothing to do with Mexican food. It is'
puts 'an experiment about bed-wetting. The Mexican'
puts 'food was just there to catch you off guard'
puts 'in the hopes that you would answer more'
puts 'honestly. Thanks again.'
puts
puts wetsBed

Ispis:
Hello, and thank you for taking the time to
help me with this experiment. My experiment
has to do with the way people feel about
Mexican food. Just think about Mexican food
and try to answer every question honestly,
with either a "yes" or a "no". My experiment
has nothing to do with bed-wetting.

Do you like eating tacos?


yes

Do you like eating burritos?


yes

Do you wet the bed?


no way!

Please answer "yes" or "no".

Do you wet the bed?


NO

-40-
Do you like eating chimichangas?
yes

Just a few more questions...


Do you like eating sopapillas?
yes

DEBRIEFING:
Thank you for taking the time to help with
this experiment. In fact, this experiment
has nothing to do with Mexican food. It is
an experiment about bed-wetting. The Mexican
food was just there to catch you off guard
in the hopes that you would answer more
honestly. Thanks again.

false

Bijaše to prilično dug program, sa puno ponavljanja. (Svi dijelovi koji se tiču hrane su bili identični, samo
se dio oko mokrenja u krevet malo razlikovao.) Ponavljanje nije baš dobra stvar. U nekoj većoj petlji se ne
bismo mogli baš najbolje snaći jer ponekad ima stvari koje želimo uraditi između određenih pitanja. U
ovakvim situacijama, najbolje je napisati vlastitu metodu. Evo i kako:

def sayMoo
puts 'mooooooo...'
end

Uh...program nije mukao kao krava. Zašto ne? Nismo mu rekli da to uradi. Hajde da pokušamo ponovo:

def sayMoo
puts 'mooooooo...'
end

sayMoo
sayMoo
puts 'coin-coin'
sayMoo
sayMoo

Ispis:
mooooooo...
mooooooo...
coin-coin
mooooooo...
mooooooo...

Ah, to je već puno bolje. (U slučaju da ne govorite francuski, to je u sredini patka. Na francuskom se patke
oglašavaju sa „coin-coin“.)

-41-
Tako, definisali smo metodu sayMoo. (Imena metoda, kao i imena varijabli, počinju malim slovom.
Postoje, ipak, iznimke kao što su + ili ==.) Zar ne trebaju metode uvijek biti povezane s nekim objektima?
Naravno da trebaju,...u ovom slučaju (kao što je to i sa –puts- i –gets-) metoda je povezana sa objektom
koji predstavlja čitav program. U slijedećem poglavlju ćemo vidjeti kako dodati metode drugim objektima.
Ali, prije nego nastavimo, samo ćemo nakratko pogledati šta su...

Parametri metoda
Primjetili ste da neke od metoda (kao -gets-, -.to_s-, -reverse-...) možete jednostavno pozvati pridružujući
ih objektu. Međutim, drugim metodama (kao što su –[+]-, -[-]-, -puts-) su potrebni parametri koji govore
objektima kako da izvrše određenu metodu. Naprimjer, ne možete napisati samo 5+, zar ne? Govorite petici
da doda/sabere, ali ne govorite šta da doda.

Parametri se dodaju metodama na slijedeći način:

def sayMoo numberOfMoos


puts 'mooooooo...'*numberOfMoos
end

sayMoo 3
puts 'oink-oink'
sayMoo # Ovdje bi se trebala pojaviti grješka, jer je parametar prazan.

Ispis:
mooooooo...mooooooo...mooooooo...
oink-oink
#<ArgumentError: wrong number of arguments (0 for 1)>

numberOfMoos varijabla je koja predstavlja parametar naše metode. Reći ću to još jednom,
numberofMoos je varijabla koja predstavlja parametar naše metode. Dakle, ako unesem u kod „sayMoo
3“, onda je parametar moje metode 3, a numberOfMoos ukazuje na tricu.

Kao što možete vidjeti, parametar je u ovom slučaju obavezan/neophodan. Kako će vaš jadni računar znati
da treba ponavaljati „mooo“ ako mu ne podesite parametar za takvu akciju.

Ako je objekat za Ruby ono što je imenica za jezik, metoda glagol, onda bi parametar bio jednak prilogu
(priloška odredba) (u našem primjeru bi nam parametar trebao otprilike reći kako da izvrši „sayMoo“) ili
ponekad kao direktnom objektu (kao –puts-, gdje se parametar ispisuje zbog komande koju –puts- daje).

Lokalne varijable
U slijedećem programu, postoje dvije varijable...:

def doubleThis num


numTimes2 = num*2
puts num.to_s+' doubled is '+numTimes2.to_s
end

doubleThis 44

-42-
Ispis:
44 doubled is 88

…te varijable su num i numTimes2. Obje su smještene unutar doubleThis metode. Ove dvije (kao i sve
varijable koje smo imali priliku vidjeti do sada) nazivaju se lokalne varijable. To znači da one
„žive“/vrijede samo unutar određene metode i da izvan nje ne mogu biti primjenjivane...pokušamo li, javit
će se grješka:

def doubleThis num


numTimes2 = num*2
puts num.to_s+' doubled is '+numTimes2.to_s
end

doubleThis 44
puts numTimes2.to_s

Ispis:
44 doubled is 88
#<NameError: undefined local variable or method `numTimes2' for
#<StringIO:0x82ba7a8>>

Nedefinisana lokalna varijabla,...mi jesmo definisali tu lokalnu varijablu, ali ona nije lokalna tamo gdje
smo je pokušali koristiti, nego je lokalna za metodu.

Možda se čini nepovoljnim, ali je to ustvari dobra stvar. To znači da nema pristupa varijablama koje se
nalaze unutar metoda, ali i da metode ne mogu pristupiti varijablama,...gdje postoji mogućnost da ih te
metode izmjene:

def littlePest var


var = nil
puts 'HAHA! I ruined your variable!'
end

var = 'You can\'t even touch my variable!'


littlePest var
puts var

Ispis:
HAHA! I ruined your variable!
You can't even touch my variable!

U ovom malom programu, postoje dvije varijable imena var: jedna unutar littlePest metode, a druga izvan
nje. Kad pozovemo metodu littlePest na izvršenje, nismo ništa drugo uradili nego prebacili string iz jedne
varijable u drugu, tako da obje ukazuju na isti string. Nakon toga littlePest ukazuje svoju lokalnu varijablu
na nil (ništa), ali to nije promijenilo vanjsku varijablu var.

Povratne vrijednosti
Možda ste primjetili da neke metode daju povratnu vrijednost kad ih pozovemo. Naprimjer, integrisana
-43-
metoda –gets- vraća string koji smo unijeli putem tastature/tipkovnice, a metoda –[+]- u 5+3 vraća
vrijednost 8. Aritmetičke metode za brojeve vraćaju brojeve, a aritmetičke metode za string vraćaju isti.

Važno je da razumijete razliku između metoda koje imaju povratne vrijednosti – daju rezultat - od metoda
koje po pozivu ispisuju informacije na ekranu, kao što to radi metoda –puts-. Obratite pažnju,...5+3 vraća
vrijednost 8, ne ispisuje informaciju 8.

Šta onda metoda –puts- vraća? Ranije nismo marili za to, ali hajde da pogledamo sada:

returnVal = puts 'This puts returned:'


puts returnVal

Ispis:
This puts returned:
nil

Dakle, prvi je –puts- vratio nil (ništa). Iako nismo testirali i drugi je vratio istu vrijednost; -puts- uvijek
vraća nil (ništa) [k.p.: primjetit ćete, ukoliko koristite irb - interactive Ruby- da će poslije -puts- biti
naznačena često i linija u kojoj stoji nil]. Na kraju, svaka metoda mora nešto vratiti, pa makar to bila i nil
vrijednost (ništa).

Napravite malu pauzu i napišite program koji će saznati šta je povratna vrijednost metode sayMoo.

Iznenađeni? Evo kako to funkcioniše: vrijednost koju metoda vraća jednaka je poslijednjoj liniji te metode.
U našem slučaju, to znači –puts 'moooo...'*numberOfMos-, što vraća nil, jer je to uvijek povratna
vrijednost metode –puts-. Dakle, ako bismo željeli da naše metode vraćaju string 'yellow submarine',
jednostavno bismo je trebali staviti na kraj.

def sayMoo numberOfMoos


puts 'mooooooo...'*numberOfMoos
'yellow submarine'
end

x = sayMoo 2
puts x

Ispis:
mooooooo...mooooooo...
yellow submarine

Da pokušamo onaj psihološki test, ponovo, ali ovaj put ćemo napisati metodu koja će postavljati pitanja za
nas. Moraće uzeti pitanje kao parametar, a kao povratnu vrijednost daće vrijednost true ako je odgovor
tačan (yes), a false ukoliko je odgovor netačan (no). (Iako smo većinom ignorisali odgovor, ipak je dobra
ideja učiniti da naša metoda vraća neku vrijednost. Možemo je takođe lakše iskoristiti za pitanje o
mokrenju kreveta.) Skratit ću uvod i pozdrav, da bi bilo lakše čitati:

def ask question


goodAnswer = false
-44-
while (not goodAnswer)
puts question
reply = gets.chomp.downcase
if (reply == 'yes' or reply == 'no')
goodAnswer = true
if reply == 'yes'
answer = true
else
answer = false
end
else
puts 'Please answer "yes" or "no".'
end
end

answer      # Ovo je naša povratna vrijednost (true or false).


end

puts 'Hello, and thank you for...'


puts
ask 'Do you like eating tacos?'      # Ovu povratnu vrijednost
zanemarujemo.
ask 'Do you like eating burritos?'
wetsBed = ask 'Do you wet the bed?'      # Ovu čuvamo u varijabli.
ask 'Do you like eating chimichangas?'
ask 'Do you like eating sopapillas?'
ask 'Do you like eating tamales?'
puts 'Just a few more questions...'
ask 'Do you like drinking horchata?'
ask 'Do you like eating flautas?'

puts
puts 'DEBRIEFING:'
puts 'Thank you for...'
puts
puts wetsBed

Ispis:
Hello, and thank you for...

Do you like eating tacos?


yes
Do you like eating burritos?
yes
Do you wet the bed?
no way!
Please answer "yes" or "no".
Do you wet the bed?
NO
Do you like eating chimichangas?
yes
Do you like eating sopapillas?
yes
Do you like eating tamales?

-45-
yes
Just a few more questions...
Do you like drinking horchata?
yes
Do you like eating flautas?
yes

DEBRIEFING:
Thank you for...

false

Nije loše, ha? Bili smo u mogućnosti dodati još pitanja (a to je sada lahko), a naš program ima znatno
manje linija u kodu! Za lijenog programera, to je stvarno veliko poboljšanje.

Još jedan veliki primjer


Mislim da bi još jedan primjer bio od pomoći da još bolje upoznate metode. Nazvat ćemo ga
englishNumber. Metoda će uzeti broj od korisnika, naprimjer 22, te ga onda vratiti kao broj izgovoren na
engleskom jeziku (u ovom slučaju string 'twenty-two'). Trenutno ćemo uvrstiti samo integer vrijednosti
između 0 i 100.

(Napomena: Ova metoda koristi novi trik da se vrati na početak, koristeći rezervisanu riječ return, a
predstavlja nam i novi izraz u grananju: elsif. Iz konteksta će se lahko izvući zaključak kako funkcionišu
oba ova nova dodatka.)

def englishNumber number

# Želimo samo brojeve između 0 i 100.


if number < 0
return 'Please enter a number zero or greater.'
end

if number > 100


return 'Please enter a number 100 or lesser.'
end

numString = '' # Ovo je varijabla za ispis rezultata.

# "left" je koliko nam još broja ostaje za ispisati.


# "write" je dio koji trenutno ispisujemo.
# "napiši" i "ostalo"... kontaš? :)

left = number
write = left/100 # Koliko stotica ima za ispisati?
left = left - write*100 # Oduzeti stotice.

if write > 0
return 'one hundred'
end

write = left/10 # Koliko desetica ima za ispisati?


-46-
left = left - write*10 # Oduzeti desetice.

if write > 0
if write == 1 # Uh-oh...
# Pošto ne možemo napisati "tenty-two" umjesto "twelve",
# moramo napraviti iznimku za ovaj slučaj.
if left == 0
    numString = numString + 'ten'
elsif left == 1
    numString = numString + 'eleven'
elsif left == 2
    numString = numString + 'twelve'
elsif left == 3
    numString = numString + 'thirteen'
elsif left == 4
    numString = numString + 'fourteen'
elsif left == 5
    numString = numString + 'fifteen'
elsif left == 6
    numString = numString + 'sixteen'
elsif left == 7
    numString = numString + 'seventeen'
elsif left == 8
     numString = numString + 'eighteen'
elsif left == 9
    numString = numString + 'nineteen'
end

# Pošto smo se pobrinuli za za cifre u jedinicama


# nije nam ostalo ništa za ispisati.
left = 0
elsif write == 2
    numString = numString + 'twenty'
elsif write == 3
    numString = numString + 'thirty'
elsif write == 4
    numString = numString + 'forty'
elsif write == 5
    numString = numString + 'fifty'
elsif write == 6
    numString = numString + 'sixty'
elsif write == 7
    numString = numString + 'seventy'
elsif write == 8
    numString = numString + 'eighty'
elsif write == 9
    numString = numString + 'ninety'
end

if left > 0
numString = numString + '-'
end
end

write = left # Koliko jedinica ima za ispisati?

-47-
left = 0 # Oduzeti jedinice.

if write > 0
if write == 1
    numString = numString + 'one'
elsif write == 2
    numString = numString + 'two'
elsif write == 3
    numString = numString + 'three'
elsif write == 4
    numString = numString + 'four'
elsif write == 5
    numString = numString + 'five'
elsif write == 6
    numString = numString + 'six'
elsif write == 7
    numString = numString + 'seven'
elsif write == 8
    numString = numString + 'eight'
elsif write == 9
    numString = numString + 'nine'
end
end
if numString == ''
# Jedino kad je "number" jednak nuli "numString"
# može biti prazan string – odnosno nula - 'zero'
return 'zero'
end

# Do ovog momenta bi trebalo da smo otkrili naš broj


# pa ostaje još samo da ga ispišemo, odnosno vratimo "numString".
numString
end

puts englishNumber( 0)
puts englishNumber( 9)
puts englishNumber( 10)
puts englishNumber( 11)
puts englishNumber( 17)
puts englishNumber( 32)
puts englishNumber( 88)
puts englishNumber( 99)
puts englishNumber(100)

Ispis:
zero
nine
ten
eleven
seventeen
thirty-two
eighty-eight
ninety-nine

-48-
one hundred

[k.p.]: INTERVENCIJA PREVODIOCA


----------------

E pa, u ovom je programu nekoliko stvari koji mi se nikako ne sviđaju, Prvo, previše je ponavljanja.
Drugo, ne radi sa brojevima preko 100. Treće, previše je zasebnih slučajeva, previše return. Hajde da,
koristeći nizove, pokušamo počistiti sve ove nedostatke:

def englishNumber number

if number < 0 # Ne uključujemo negativne brojeve.


return 'Please enter a number that isn\'t negative.'
end

if number == 0
return 'zero'
end

# Nema više posebnih slučajeva! Nema return!


numString = '' # Ovo je string koji ćemo imati za rezultat.

onesPlace = ['one', 'two', 'three', 'four', 'five', 'six', 'seven',


'eight', 'nine']

tensPlace = ['ten', 'twenty', 'thirty', 'forty', 'fifty', 'sixty',


'seventy', 'eighty', 'ninety']

teenagers = ['eleven', 'twelve', 'thirteen', 'fourteen', 'fifteen',


'sixteen', 'seventeen', 'eighteen', 'nineteen']

# "left" je koliko nam još broja ostaje za ispisati.


# "write" je dio koji trenutno ispisujemo.
# "napiši" i "ostalo"... kontaš? :)

left = number
write = left/100 # Koliko stotica ima za ispisati?
left = left - write*100 # Oduzeti stotice.

if write > 0

# Evo sad jedan mali trik :


hundreds = englishNumber write
numString = numString + hundreds + ' hundred'

# To se zove "rekurzija". Šta sam upravo uradio.


# Rekao sam ovoj metodi da pozove sama sebe ali s parametrom
# "write" umjesto "number". Upamtite da je "write" trenutno broj
# stotica koje treba ispisati. Nakon što dodamo stotice promjenjivoj
# "numString", a nakon toga dodajemo ' hundred'. Tako, na primjer
# ako smo pozvali englishNumber sa parametrom 1999 ("number" = 1999)
# u tom momentu bi "write" bio 19 a "left" bi bio 99.
# [k.p.]: devetnaest stotina i ostatak 99.
# Najlijenja stvar koji možemo uraditi sad je da naredimo metodi

-49-
# englishNumber da ispiše 'nineteen' i samo mu doda ' hundred', a
# onda ostatak metode ispiše 'ninety-nine'.

if left > 0
# Da ne bismo napisali 'two hundredfifty-one'...
numString = numString + ' '
end

end

write = left/10 # Koliko desetica ima za ispisati?


left = left - write*10 # Oduzeti desetice.

if write > 0
if ((write == 1) and (left > 0))
# Pošto ne možemo napisati "tenty-two" umjesto "twelve",
# moramo napraviti iznimku za ovaj slučaj.

numString = numString + teenagers[left-1]


# Faktor "-1" postavljen je iz razloga što je [3] jednak 'fourteen', a
ne 'thirteen'.

# Pošto smo se pobrinuli za za cifre u jedinicama


# nije nam ostalo ništa za ispisati.
left = 0

else

numString = numString + tensPlace[write-1]


# Faktor "-1" stavljamo jer je tensPlace[3] jednak 'forty', a ne
'thirty'.

end

if left > 0
# Da ne bismo pisali 'sixtyfour' (spojeno)...
numString = numString + '-'
end

end

write = left # Koliko jedinica ima za ispisati?


left = 0 # Oduzeti jedinice.

if write > 0
numString = numString + onesPlace[write-1]
# Faktor "-1" postavljamo jer je onesPlace[3] jednak 'four', a ne
'three'.

end

# Sad jednostavno ispišemo/vratimo "numString"...

-50-
numString
end

puts englishNumber( 0)
puts englishNumber( 9)
puts englishNumber( 10)
puts englishNumber( 11)
puts englishNumber( 17)
puts englishNumber( 32)
puts englishNumber( 88)
puts englishNumber( 99)
puts englishNumber(100)
puts englishNumber(101)
puts englishNumber(234)
puts englishNumber(3211)
puts englishNumber(999999)
puts englishNumber(1000000000000)

Ispis:
zero
nine
ten
eleven
seventeen
thirty-two
eighty-eight
ninety-nine
one hundred
one hundred one
two hundred thirty-four
thirty-two hundred eleven
ninety-nine hundred ninety-nine hundred ninety-nine
one hundred hundred hundred hundred hundred hundred

Ahhhh.... Tako je već mnogo bolje. Program je malo gušći, pa sam iz tog razloga napisao dosta komentara.
Radi čak i sa velikim brojevima...iako ne baš nabolje, ne onako kako sam se nadao. Na primjer, 'one trilion'
(milijarda) bi ljepše izgledalo, nego vrijednost koju vidimo na kraju ispisa,...ili 'one milion milion' (iako su
sve tri vrijednosti tačne). Ustvari, mogli biste to upravo vi i uraditi...

Par stvarčica za oprobati


 Proširite program englishNumber. Prvo, ubacite hiljadinke. Na taj način će vam program pisati
jedna hiljada umjesto deset stotina ili deset hiljada umjesto jedna stotina stotina.
 Nakon ovog, napravite još jedno proširenje. Dodajte milionite dijelove, tako da se u ispisu pojavi
milion umjesto hiljada hiljaada. Onda idite sve dalje i dalje u proširivanju opsega. Šta mislite,
koliko daleko možete ići?
 Kako bi bilo da napišete program weddingNumber? Trebao bi raditi slično kao i englishNumber,
osim što bi trebalo dodati riječ 'and' posvuda, vraćajući vrijednosti kao što je 'nineteen hundred and
seventy and two' ili na neki drugi način opisati kako trebaju izgledati pozivnice za vjenčanje. Dao
bih vam još primjera, ali ni sam baš najbolje ne razumijem kako to ide. Možda biste trebali kakvog
organizatora vjenčanja da vam pomogne?
 „Ninety-nine bottles of beer...“ sjećate li se tog programa? Koristeći princip prisutan u
englishNumber, ispišite tekst ove pjesme na pravi način, ovaj put. Kaznite svoj računar: neka počne
-51-
od 9999 (Mada, nemojte odabrati preveliki broj, jer,...pisanje svih tih flaša na ekranu vašeg
računara moglo bi potrajati. Sto hiljada flaša bi stvarno potrajalo; a ako li biste odabrali milion,
onda biste kaznili ne samo računar, nego i sebe.)

Čestitam! Od ovog momenta, možete se pohvaliti da ste programeri! Naučili ste sve što je potrebno da se
napiše jedan program „od nule“. Ako trenutno imate ideja koje biste mogli iskoristiti za pisanje
programa,...učinite to odmah! Pretvorite svoje ideje u funkcionalne programe, pokušajte!

Naravno, pisanje programa „od nule“ može nekad i da potraje. Zašto gubiti vrijeme i pisati kod koji je neko
već napisao? Hoćete li da vaš program šalje e-mail? Ili želite pohraniti ili učitati fajlova sa vašeg računara?
Kako vam se čini generisanje web stranica za tutorial koje stvarno izvršavaju kod, svaki put kad ih učitate?
Ruby ima veliki broj različitih objekata koji nam mogu pomoći da napišemo bolje programe za što manje
vremena. Zato...idemo dalje...

9. Klase
Do ovog momenta, vidjeli smo različite vrste, ili klase, objekata: string, integer, float, nizove i par
specijalnih objekata (true, false, nil) o kojima ćemo nešto kasnije. Klase u Ruby uvijek počinju velikim
slovom: String, Integer, Float, Array,... Kad želimo kreirati novi objekat određene klase, onda koristimo
new:

a = Array.new + [12345] # Dodavanje niza.


b = String.new + 'hello' # Dodavanje stringa.
c = Time.new

puts 'a = '+a.to_s


puts 'b = '+b.to_s
puts 'c = '+c.to_s

Ispis:
a = 12345
b = hello
c = Sat Jan 31 07:18:32 GMT 2009

Iz razloga što nizove i znakove možemo kreirati pomoću [...] i '...' (respektivno), rijetko koristimo new.
(Iako to možda nije očigledno iz pređašnjeg primjera, za kreiranje praznog stringa koristimo String.new, a
za prazan niz koristimo Array.new) Treba napomenuti da su brojevi izuzetak/iznimka: ne možete kreirati
integer koristeći Integer.new, nego jednostavno taj integer napišete.

Klasa za vrijeme – „Time“


Klasa za vrijeme? O čemu se tu radi?

Objekat Time predstavlja određeni vremenski momenat. Na ovaj objekat možemo dodati ili oduzeti
određene (brojčane) vrijednosti, da bismo dobili „novo“ vrijeme, odnosno neki drugi vremenski momenat:
ako na trenutno vrijeme dodamo 1.5, onda ćemo kao rezultat dobiti vrijeme 1.5 sekundu kasnije:

time = Time.new # Momenat koji ste dobili u trenutku ispisa.


time2 = time + 60 # Minuta kasnije.

puts time
puts time2
-52-
Ispis:
Sat Jan 31 07:18:32 GMT 2009
Sat Jan 31 07:19:32 GMT 2009

Ovaj objekat možete koristiti i da biste kreirali određen vremenski momenat,...koristeći Time.mktime:

puts Time.mktime(2000, 1, 1) # Y2K.


puts Time.mktime(1976, 8, 3, 10, 11) # Datum mog rođenja.

Ispis:
Sat Jan 01 00:00:00 GMT 2000
Tue Aug 03 10:11:00 GMT 1976

Napomena: datum mog rođenja sadrži format Pacific Daylight Savings Time (PDT). Kada je nastupila
2000.-ta godina, vrijeme je dobilo Pacific Standard Time (PST) format, bar za nas sa zapadne obale.
Zagrade služe da grupišu parametre mktime. Što više parametara dodate, tačnije vrijeme ćete dobiti.

Možete koristiti poredbene metode da uporedite određena vremena (manja cifra je starije), te ako ih
oduzmete jedno od drugog, dobijete broj sekundi između njih. Pokušajte, igrajte se malo!

Par stvarčica za oprobati


 Milijarda sekundi...napišite program koji će reći prije koliko sekundi ste rođeni (ako umijete).
Saznajte kada ćete biti milijardu sekundi stari (ili ste to već)? Program će vam pomoći da to
označite na svoj kučnom kalendaru J
 Sretan rođendan! Napišite program koji će osobu pitati godinu, mjesec i dan rođenja. Otkrijte na
taj način koliko je osoba stara, pa joj za svaku godinu dajte jedan...SPANK!

„Hash“ klasa
Još jedna korisna klasa je „Hash“. Ne može se reći da je ovaj objekat poput niza, jer nizovi imaju mnogo
slotova, indeksiranih brojevima, počevši od nule, smještenih u redove. Za „hash“ ne možemo reći da su
smješteni u redove, a u slotove se može ubaciti svaki objekat, ne samo broj [k.p.: indeksirani su i po nekim
drugim vrijednostima, ne samo brojevima, kako je to slučaj kod nizova]. Dobro je koristiti „hash“ kada
imate dosta stvari koje želite imati pri ruci, a te se stvari ne mogu baš poredati u niz uređen brojčanim
indeksom. Naprimjer, boje koje sam koristio za ovaj tutorial:

colorArray = [] # isto kao Array.new


colorHash = {} # isto kao Hash.new

colorArray[0] = 'red'
colorArray[1] = 'green'
colorArray[2] = 'blue'
colorHash['strings'] = 'red'
colorHash['numbers'] = 'green'
colorHash['keywords'] = 'blue'

colorArray.each do |color|
-53-
puts color
end

colorHash.each do |codeType, color|


puts codeType + ': ' + color
end

Ispis:
red
green
blue
strings: red
keywords: blue
numbers: green

Kad koristim nizove, moram pamtiti da je slot 0 za string, slot 1 za integer, itd. Međutim, „hash“ mi
dozvoljava da znatno pojednostavim stvari! Slot 'strings' sadrži boju za tekst, naravno. Ništa ne moram
pamtiti. Primjetit ćete da, kad smo koristili –each-, program nije ispisao objekte unutar „hash-a“
redoslijedom kojim smo ga mi unosili u programu. (Možda nisu dok sam ja ovo pisao, kod mene. Možda
su neki drugi put, nikad se ne zna s „hash“ klasama.) Nizovi su ti koji sve drže u savršenom redu – „hash“
klase nisu za to zadužene.

Iako ljudi većinom koriste string da bi imenovali slotove „hash“ klasa, moguće je umetnuti bilo kakav
objekat, čak i nizove ili druge „hash“ klase (iako mi trenutno ne pada na pamet zašto biste radili ovo
poslijednje):

weirdHash = Hash.new
weirdHash[12] = 'monkeys'
weirdHash[[]] = 'emptiness'
weirdHash[Time.new] = 'no time like the present'

Hash klase i nizovi su korisni u različitim situacijama, pa je na vama da odaberete šta je bolje koristiti za
određeni problem, koji sebi postavite.

Proširivanje klasa
Na kraju prošlog poglavlja, napisali smo metodu koja je „čitala“ brojeve. Međutim, to nije bila metoda
koju smo mogli primjeniti na neki integer, nego jednostavno – metoda koja je predstavaljala čitav program.
Ne bi li bilo lijepo kad bismo mogli jednostavno napisati nešto kao 22.to_eng umjesto englishNumber 22?
Evo kako bi to izgledalo:

class Integer

def to_eng
if self == 5
english = 'five'
else
english = 'fifty-eight'
end

-54-
english
end

end

# Dobro bi bilo da testiram na par brojeva...


puts 5.to_eng
puts 58.to_eng

Ispis:
five
fifty-eight

Ja sam testirao program, izgleda da radi. ;)

Dakle, definisali smo metodu za integer „uskačući“ u Integer klasu, definišući metodu unutar nje. Sada će
svi integeri biti podvrgnuti ovoj (pomalo nepotpunoj) metodi. Ustvari, ako vam se nije sviđalo kako
metoda za stringove -to_s- radi, možete je jednostavno redefinisati na način sličan ovom primjeru...ali vam
ne bi preporučio da je dirate, bilo kako bilo!
Predefinisane metode programskog jezika najbolje je ostaviti onakvim kakve jesu i u slučaju da želimo
nešto novo – napraviti nove, vlastite metode ili klase.

Zbunjeni...? Da prođemo još jednom kroz ovaj poslijednji program. Sve do sada, kad god bismo izvršili
kod ili definirali metode, radili smo to u programu kao objektu. U pređašnjem primjeru programa, program
kao objekat smo ostavili i ušli u Integer klasu. Unutar nje smo definisali metodu (što je čini integer
metodom) koju mogu koristiti svi integer objekti. Unutar te metode koristimo rezervisanu riječ –self- da
bismo ukazali na objekat koji ta metoda koristi (integer).

Kreiranje klasa (classes)


Pred nama su bile brojne klase različitih klasa objekata. Međutim, vrlo je lahko napraviti i onu koja u Ruby
inače ne postoji. Na sreću, kreiranje nove klase je podjednako jednostavno kao i proširivanje neke
postojeće. Recimo da smo htjeli napraviti kockicu za „Ne ljuti se čovječe“ u Ruby. Ovako bi njena klasa
izgledala:

class Die

def roll
1 + rand(6)
end

end

# Da sad napravimo par kockica...


dice = [Die.new, Die.new]

# ...a onda ih „bacimo“.


dice.each do |die|
puts die.roll
end

-55-
Ispis:
6
1

(Ako ste preskočili dio u kome smo učili o generisanju slučajnog broja, evo male pomoći za vas,...rand(6)
generiše slučajni broj u vrijednosti između 0 i 5.)

To je sve! Imate vlastite objekte. Bacite kockice nekoliko puta (refresh [F5] na originalnog stranici
http://pine.fm/LearnToProgram/) i pogledajte šta će se desiti.

Možemo mi definisati razne metode za naše objekte...ali nešto ipak nedostaje. Rad s ovim objektima
podsjeća uveliko na programiranje prije upoznavanja s varijablama. Pogledajte, naprimjer, naše kockice.
Možemo i „baciti“ i svaki put će nam dati različite brojeve. Ali, ako bismo htjeli ostati na tom broju, onda
bi morali napraviti varijablu koja bi taj broj zadržala, dakle, ukazivala na broj. Ukoliko bismo morali pratiti
kockicu, ne bismo morali pratiti i brojeve.

Međutim, ako bismo pokušali pohraniti broj koji smo dobili pri bacanju kockice u (lokalnu) varijablu, on bi
trajao do završetka bacanja. Treba nam, dakle, neki drugi tip varijable u koji ćemo smjestiti naš broj:

Neposredne varijable
Obično, kad hoćemo govoriti o znakovima/tekstu, onda govorimo o stringu. Međutim, mogli bismo
slobodno reći i da je to string objekat. Ponekad programeri nazovu instanca klase String, međutim, to je
samo uglađen način (i prilično dug, ako mene pitate) da se kaže string. Instanca neke klase je jednostavno
objekt koji pripada toj klasi.

Tako dakle, neposredne varijable (instance) su varijable nekog objekta. Lokalne varijable, koje pripadaju
nekoj metodi, traju do završetka metode. S druge strane, neposredne (instance) varijable nekog objekta
traju sve dok taj objekat traje. Da bi smo razlikovali obične lokalne varijable od neposrednih, koristimo
znak @ koji stavljamo ispred imena varijable:

class Die

def roll
@numberShowing = 1 + rand(6)
end

def showing
@numberShowing
end

end

die = Die.new
die.roll
puts die.showing
puts die.showing
die.roll
puts die.showing
puts die.showing

Ispis:
-56-
6
6
6
6

Vrlo dobro! Prilagođena metoda „roll“ baca kockice, a „showing“ nam govori koji broj kockica pokazuje.
Međutim, šta ako pokušamo pogledati koje ćemo brojeve dobiti prije nego bacimo kockice (prije nego
definišemo @numberShowing)?

class Die

def roll
@numberShowing = 1 + rand(6)
end

def showing
@numberShowing
end

end

# Pošto ovu kockicu neću ponovo koristiti


# ne trebam je ni čuvati u varijabli.
puts Die.new.showing

Ispis:
nil

Hmmm,...ako ništa, nije nam se javila nikakva grješka. Svejedno, nema smisla da nam se kocka „ne baci“,
ili šta god da povratna vrijednost „nil“ znači. Bilo bi lijepo kad bi se naše kockica mogla „podesiti“ tik prije
nego što je bacimo. Za tu svrhu koristimo –initialize-:

class Die

def initialize
# Jednostavno ću „baciti“ kockicu, iako
# bismo mogli učiniti s njom i štošta drugo
# naprimjer, da stalno pokazuje broj 6.
roll
end

def roll
@numberShowing = 1 + rand(6)
end

def showing
@numberShowing
end

end
-57-
puts Die.new.showing

Ispis:
2

Kada se kreira objekat, njegova –initialize- metoda (ako je definisana) uvijek se poziva.

Naše su kocke skoro pa savršene. Jedno što im možda nedostaje je da nam metoda kaže koju stranu kocke
pokazuje...zašto ne biste napravili metodu koja upravo to pokazuje. Vratite se čitanju kad završite (i nakon
što se svoj program testirali, naravno)! Ne dozvolite da neko podesi kockicu tako da može pokazati i
sedmicu!

Tako dakle, pokrili smo ovim poglavljem dosta zanimljivih stvari. Jeste pomalo komplikovano, tako da ću
navesti još jedan primjer. Recimo da želimo napraviti jednostavnog virtualnog ljubimca, bebu zmaja. Kao i
većina beba, trebala bi biti u mogućnosti da jede, spava i . . . „kaki“, što će reći da ćemo je morati hraniti,
staviti u krevet i „izvoditi napolje“. Unutar bebe zmaja trebao bi postojati metod koji će pratiti glad,
pospanost i digestiju, ali mi nećemo moći da vidimo sve to, isto kao što bebu ne možemo pitati „Jesi li
gladna?“. Dodaćemo takođe još nekoliko zanimljivih sitnica koje će povećati interakciju sa našom bebom
zmajem, a kad se rodi daćemo mu ime (šta god da unesete u tu novu metodu, ono se prenosi do –initialize-
metode). U redu, da pokušamo:

class Dragon

def initialize name


@name = name
@asleep = false
@stuffInBelly = 10 # Pun stomak.
@stuffInIntestine = 0 # Ne mora ići „vani“.

puts @name + ' is born.'


end

def feed
puts 'You feed ' + @name + '.'
@stuffInBelly = 10
passageOfTime
end

def walk
puts 'You walk ' + @name + '.'
@stuffInIntestine = 0
passageOfTime
end

def putToBed
puts 'You put ' + @name + ' to bed.'
@asleep = true

3.times do
if @asleep
passageOfTime
-58-
end

if @asleep
puts @name + ' snores, filling the room with smoke.'
end
end

if @asleep
@asleep = false
puts @name + ' wakes up slowly.'
end

end

def toss
puts 'You toss ' + @name + ' up into the air.'
puts 'He giggles, which singes your eyebrows.'
passageOfTime
end

def rock
puts 'You rock ' + @name + ' gently.'
@asleep = true
puts 'He briefly dozes off...'
passageOfTime
if @asleep
@asleep = false
puts '...but wakes when you stop.'
end
end

private

# "private" znači da metode koje su ovdje definisane jesu


# metode interne za objekat (Možete nahraniti svoj zmajčeka
# ali ga ne možete upitati da li je gladan.)

# Metode se mogu završavati i sa "?".


# Obično tako završavamo samo one metode koje
# daju povratnu vrijednost true ili false kao:
@stuffInBelly <= 2
end

def poopy?
@stuffInIntestine >= 8
end

def passageOfTime
if @stuffInBelly > 0
# Pomjeri hranu iz stomaka u crijevo.
@stuffInBelly = @stuffInBelly - 1
@stuffInIntestine = @stuffInIntestine + 1
else # Umrije nam zmajić od gladi!
if @asleep
@asleep = false

-59-
puts 'He wakes up suddenly!'
end
puts @name + ' is starving! In desperation, he ate YOU!'
exit # Ovdje se program završava.
end

if @stuffInIntestine >= 10
@stuffInIntestine = 0
puts 'Whoops! ' + @name + ' had an accident...'
end

if hungry?
if @asleep
@asleep = false
puts 'He wakes up suddenly!'
end
puts @name + '\'s stomach grumbles...'
end

if poopy?
if @asleep
@asleep = false
puts 'He wakes up suddenly!'
end
puts @name + ' does the potty dance...'
end
end

end

pet = Dragon.new 'Norbert'


pet.feed
pet.toss
pet.walk
pet.putToBed
pet.rock
pet.putToBed
pet.putToBed
pet.putToBed
pet.putToBed

Ispis:
Norbert is born.
You feed Norbert.
You toss Norbert up into the air.
He giggles, which singes your eyebrows.
You walk Norbert.
You put Norbert to bed.
Norbert snores, filling the room with smoke.
Norbert snores, filling the room with smoke.
Norbert snores, filling the room with smoke.
Norbert wakes up slowly.
You rock Norbert gently.
He briefly dozes off...

-60-
...but wakes when you stop.
You put Norbert to bed.
He wakes up suddenly!
Norbert's stomach grumbles...
You put Norbert to bed.
He wakes up suddenly!
Norbert's stomach grumbles...
You put Norbert to bed.
He wakes up suddenly!
Norbert's stomach grumbles...
Norbert does the potty dance...
You put Norbert to bed.
He wakes up suddenly!
Norbert is starving! In desperation, he ate YOU!

Opa! Naravno, bilo bi puno bolje da u ovom programu ima malo više interakcije, ali taj dio možete doraditi
poslije. U ovom primjeru sam pokušao pokazati samo dijelovi koji se odnose na kreiranje nove klase –
dragon -.

U ovom smo primjeru vidjeli nekoliko primjera. Prvi primjer je: -exit- će okončati program tačno na onom
mjestu na kojem se nalazi. Drugi: -private- rezervisana riječ koju smo stavili u sred definicije klase.
Mogao sam je izostaviti, ali sam htio da napravim razliku među metodama koje su stvari koje možemo
„učiniti“ našem zmaju, a druge se jednostavno samo događaju s njim. Mislite o ovim metodama kao o
onom što je „pod haubom“: ukoliko niste automehaničari, sve što trebate znati o automobilima da biste ih
vozili su pedale gasa i kočnice i volan. Programer bi mogao ove akcije nazvati public interface / vidljivo
sučelje. Međutim, kada treba aktivirati okidač zračnog jastuka, za to se brinu interni sistemi u automobilu,
sistemi za koje obični vozač i ne zna (niti mora da zna).

Hajde da navedemo konkretan primjer kako predstaviti automobil u video igri (što je moj stvarni posao).
Prvo bi trebalo razlučiti kako trebaju izgledati javna sučelja, odnosno, drugim riječima, koje bi metode
igrači bili u mogućnosti pozvati nad objektima koje sačinjavaju automobil. Trebalo bi da su u mogućnosti
tisnuti pedalu gasa, pedalu kočnice, ali i da budu u mogućnosti odrediti kojom jačinom će stisnuti pedalu
(velika je razlika samo je dotaći i stisnuti do poda). Trebalo bi i da budu u mogućnosti okretati volan i opet,
odrediti kojom brzinom i za koji ugao. Pretpostavljate da bismo mogli ići sve dalje i dalje,...na kvačilo,
žmigavce, bacač granata, nitro pogon, itd ...zavisno od vrste igre koju pravimo.

Međutim, u unutrašnjosti automobila trebalo bi se dašavati daleko više; ostale stvari, koje auto treba su
brzina, smjer, pozicija (u najjednostavnijem). Ovi atributi bi se mijenjali pritiskom na papučicu gasa ili
kočnice i okretanje volana, naravno, ali njih korisnik ne bi mogao mijenjati direktno (što bi bila dobra
osnova za warp). Mogli biste takođe dodati pređeni put, ili oštećenje automobila prilikom utrkivanja...sve
nevedeno bi bilo „unutrašnje“ u objektima prisutnim u automobilu.

Par stvarčica za oprobati


 Napravite klasu OrangeTree. Trebala bi imati metodu height koja bi kao povratnu vrijednost
davala visinu i metodu onYearPasses koja, kada se pozove, utvrdi starenje. Svake godine, drvo
postaje sve visočije (koliko vi mislite da bi drvo narandže trebalo porasti godišnje) i nakon
određenog vremena, kad prođe mnogo godina, drvo bi trebalo istruhnuti. Prvih nekoliko godina, ne
bi trebalo proizvoditi voće, ali nakon određenog vremena, počinje rađati; valjda, što je starije drvo,
biće više plodova svake godine,...šta god vama bude smisleno. Naravno, trebalo bi biti u stanju
countTheOranges (probrojati narandže – povratna vrijednost je količina na drvetu) i
pickAnOrange (ubrati narandžu,...što smanjuje @orangeCount za jednu narandžu i vraća string
koji govori kako je ukusna narandža bila, ili vraća informaciju da su sve narandže ubrane).
Pobrinite se i da sve narandže koje ne uberete opadnu prije nego dođe nova godina/sezona.
-61-
 Napravite program koji će dati malo više interakcije sa bebom zmaja. Trebali biste u mogućnosti
dati komande kao što su nahrani i hodaj, tako da bi se ove metode mogle izvršiti nad zmajem.
Naravno, kako unosite samo tekt (strings) program će morati da provjeri unos i pozove na osnovu
unosa odgovarajuću metodu, što bi trebalo izvesti preko neke vrste dispečera metoda.

Time smo došli do kraja ovog poglavlja! Ali,...čekajte malo...ne rekoh vam ništa o onim klasama koje šalju
e-mail, pohranjuju ili učitavaju dokumente, o kreiranju prozora i dugmića, ili 3D svijetu ili,...bilo čemu!

Ah, toliko različitih klasa postoji, koje su vam na raspolaganju, da nije moguće pokazati sve njih; pa, ni ja
ne znam većinu njih! Ono što vam mogu pokazati je, gdje da pronađete njih i nešto više o njima, tako da
biste mogli naučiti one koje želite koristiti u svojim programima. Prije nego vas otpremim, ima još jedna
stvar u Ruby koju trebate znati, nešto što većina drugih programskih jezika nema, a bez čega se
jednostavno ne može živjeti: blokovi i procedure,...

10. Blokovi i procedure


Ovo su definitivno neke od najzanimljivijih stvari koje Ruby ima.
Imaju njih i neki drugi programski jezici, iako ih oni nazivaju drukčijim imenima, ali oni najpopularniji ih
nemaju – stvarno šteta!

Šta je to tako cool i koje su to stvari cool u Ruby? Ono što je ustvari sjajno je da možemo odvojiti dio koda,
jedan blok (block), umotati ga u jedan drugi objekat (nazvan Proc), smjestiti ga u varijablu ili predati
nekoj metodi i izvršiti taj dio kad poželimo (čak i više puta, ako poželimo). Dakle, liči pomalo na metodu,
osim što nije vezano za objekat (ono ustvari jeste objekat) i može se pohraniti ili predati nekoj metodi kao
bilo koji drugi objekat. Mislim da je vrijeme za primjer:

toast = Proc.new do
puts 'Cheers!'
end

toast.call
toast.call
toast.call

Ispis:
Cheers!
Cheers!
Cheers!

Dakle, kreirao sam -Proc- (što bi trebalo da je skraćenica od „procedure“, ali što je još važnije, rimuje se
sa „block“) koji je sadržavao jedan blok koda, a nakon toga sam pozvao proceduru tri puta. Primjetit ćete
da je plaho nalik na metode.

Ustvari, procedure su još sličnije metodama nego sam vam ja to pokazao u ovom primjeru, jer blokovi
mogu sadržavati parametre:

doYouLike = Proc.new do |aGoodThing|


puts 'I *really* like '+aGoodThing+'!'

-62-
end

doYouLike.call 'chocolate'
doYouLike.call 'ruby'

Ispis:
I *really* like chocolate!
I *really* like ruby!

Dobro,...vidjesmo šta su procedure i blokovi, kako ih koristiti,...a da li smo shvatili poentu? Zašto
jednostavno ne koristiti metode? E, pa...zato što postoje neke stvari koje s metodama jednostavno ne
možete učiniti. Da budem precizniji, ne možete uvoditi jednu metodu u drugu (ali procedure u metode
možete), a metode ne mogu kao povratnu vrijednost dati druge metode (ali mogu vraćati procedure). Da
pojednostavim, razlog je što su procedure objekti, a metode to nisu.

(Usput, je li vam poznat išto od ovoga? Aha, vidjeli ste vi blokove i ranije...kad smo učili iteratore. Hajde
da popričamo malo više o tome.)

Metode koje prihvaćaju procedure


Kad proceduru uvrstimo u neku metodu, onda možemo kontrolisati kako ili koliko puta ćemo pozvati tu
proceduru. Naprimjer, recimo da nešto želimo uraditi prije i nakon što se dio koda izvrši:

def doSelfImportantly someProc


puts 'Everybody just HOLD ON! I have something to do...'
someProc.call
puts 'Ok everyone, I\'m done. Go on with what you were doing.'
end

sayHello = Proc.new do
puts 'hello'
end

sayGoodbye = Proc.new do
puts 'goodbye'
end

doSelfImportantly sayHello
doSelfImportantly sayGoodbye

Ispis:
Everybody just HOLD ON! I have something to do...
hello

Ok everyone, I'm done. Go on with what you were doing.

Everybody just HOLD ON! I have something to do...


goodbye
Ok everyone, I'm done. Go on with what you were doing.

-63-
Možda se na prvi pogled ovaj primjer i ne čini tako spektakularnim, ali on to jeste :o). Postalo je
uobičajeno u programiranju imati striktne zahtjeve kad se šta treba izvršiti. Ako, naprimjer, želite spasiti
neki fajl, morate otvoriti fajl, ispisati informacije koje želite imati, i onda zatvoriti fajl. Ako ga zaboravite
zatvoriti, svašta bi se moglo desiti. No, svaki put kad želite spasiti ili učitati fajl, morate uraditi opet isto:
otvoriti ga, izvršiti unos ili izmjenu, a onda ga zatvoriti. Sve je to naporno i brzo se zaboravlja. U Ruby,
spašavanje (ili učitavanje) fajlova funkcioniše na sličan način kao u prethodnom primjeru, tako da se ne
morate brinuti nizašta drugo osim onoga što ustvari želite spasiti/sačuvati. (U narednom poglavlju ću vam
pokazati gdje ćete naći stvari koje će vam pomoći da uradite stvari kao što je spašavanje ili učitavanje
fajlova).

Takođe možete napisati i metode koje će utvrditi koliko puta ili čak da li uopšte pozvati proceduru. Evo
metode koja će pozvati proceduru za upola manje vremena i još jedne koju ćemo pozvati dvaput:

def maybeDo someProc


if rand(2) == 0
someProc.call
end
end

def twiceDo someProc


someProc.call
someProc.call
end

wink = Proc.new do
puts '<wink>'
end

glance = Proc.new do
puts '<glance>'
end

maybeDo wink
maybeDo glance
twiceDo wink
twiceDo glance

Ispis:
<glance>
<wink>
<wink>
<glance>
<glance>

(Na originalnoj stranici [http://pine.fm/LearnToProgram/] vidjet ćete svaki put kad pristupite stranici ili
uradite refresh, da će se pojaviti drukčiji rezultat.) Ovo su neke od raširenijih primjena procedura, koje
nam daju mogućnost da uradimo stvari koje ne bismo mogli koristeći samo metode. Naravno, mogli bismo
napisati metodu da namigne dvaput, ali ne bismo mogli napisati metodu da uradimo „nešto“ dvaput!

Prije nego nastavimo, još jedan mali primjer. Do ovog momenta, procedure su prikazane na prilično sličan
način, kad se uzajamno porede. Ovaj put će biti znatno drukčije, da biste vidjeli koliko metoda zavisi od
procedura koje su u njoj sadržane. Naša metoda će tretirati objekat i proceduru,...i pozvati proceduru nad
-64-
tim objektom. Ako procedura vrati „false“, prekidamo aplikaciju. u suprotnom pozvaćemo proceduru s
vraćenim objektom. Proces će trajati sve dok ne dobije povratnu vrijednost „false“ (koju je bolje da uradi
što prije, da program ne padne). Metoda treba da vrati poslijednju vrijednost koja nije „false!“.

def doUntilFalse firstInput, someProc


input = firstInput
output = firstInput

while output
input = output
output = someProc.call input
end

input
end

buildArrayOfSquares = Proc.new do |array|


lastNumber = array.last
if lastNumber <= 0
false
else
array.pop                                # Uzmemo poslijednji broj u
nizu...
array.push lastNumber*lastNumber         # ...zamijenimo ga njegovim
kvadratom
array.push lastNumber-1                  # ...nakon čega slijedi broj
manji za 1 number.
end
end

alwaysFalse = Proc.new do |justIgnoreMe|


false
end

puts doUntilFalse([5], buildArrayOfSquares).inspect


puts doUntilFalse('I\'m writing this at 3:00 am; someone knock me
out!', alwaysFalse)

Ispis:
[25, 16, 9, 4, 1, 0]
I'm writing this at 3:00 am; someone knock me out!

Dobro, bijaše to prilično čudan primjer, priznajem. Međutim, ovaj primjer pokazuje koliko su različite
primjene metoda kad im se daju različite procedure.

Metoda –inspect- je vrlo slična metodi -to_s-, osim što na string koji vraća pokušava pokazati kod koji je
namijenjen za izgradnju objekta koji smo mu proslijedili. U ovom primjeru, pokazuje nam čitav niz
(array), nakon što prvi put pozovemo metodu doUntilFalse. Takođe, možete uočiti da ustvari nikad nismo
kvadrirali nulu na kraju niza, ali kako je kvadrat nule opet nula, nismo ni morali. Pošto je alwaysFalse
uvijek netačno, doUntilFalse metoda nije drugi put uradila apsolutno ništa kad smo je pozvali; samo je
vratila ono što smo joj proslijedili.

-65-
Metode čije su povratne vrijednosti procedure
Jedna od mnogih “strava” stvari koje možemo uraditi s procedurama je da ih kreiramo i dobijemo kao
povratnu vrijednost metoda. To nam dozvoljava mnogo lude programerske moći (stvari impresivnih imena,
kao što su lijena evaluacija, beskonačne strukture podataka), ali stvar je u tome što ja to skoro nikad ne
koristim u praksi, niti se sjećam da sam ikoga vidio da je uradio nešto tako u svom kodu. Mislim da je to
jedna od onih stvari koje na kraju i ne iskoristimo u Ruby, ili nas možda Ruby samo ohrabruje da
pokušamo naći i drugačija riješanja. Ne znam. U svakom slučaju, samo ću navesti ovo kao opciju.

U ovom primjeru, metoda –compose- uzima dvije procedure i kao povratnu vrijednost daje treću, koja, kad
se pozove, poziva prvu proceduru i njen rezultat šalje u drugu.

def compose proc1, proc2


Proc.new do |x|
proc2.call(proc1.call(x))
end
end

squareIt = Proc.new do |x|


x * x
end

doubleIt = Proc.new do |x|


x + x
end

doubleThenSquare = compose doubleIt, squareIt


squareThenDouble = compose squareIt, doubleIt

puts doubleThenSquare.call(5)
puts squareThenDouble.call(5)

Ispis:
100
50

Napomena: važno je reći da se –proc1- morala naći unutar zagrade da bi bila izvršena prije –proc2-.

Proslijeđivanje blokova (ne procedura) u metode


Dobro, ovo je bio dio zanimljiv za akademsku upotrebu, ali i pomalo mučan za koristiti. Veliki je problem
je što postoje tri koraka kroz koja moramo proći (definisanje metode, kreiranje procedure i pozivanje
metode koja sadrži tu proceduru), a moglo bi ih biti samo dva (definisanje metode i
proslijeđivanje/uvrštavanje bloka koda odmah u nju, bez korištenja procedure), pošto većinom više ne
želite koristiti proceduru/blok nakon što ih jednom provučete kroz metodu. Eh, pa, trebali biste znati da je
to Ruby sve skontala za nas! Ustvari, svaki put kad smo upotrebljavali iteratore, koristili smo ovo.

Prvo ću dati jedan mali primjer, pa ćemo onda na objašnjenja:

class Array

-66-
def eachEven(&wasABlock_nowAProc)
isEven = true
# Počinjemo sa "true" jer nizovi počinju brojem 0, koji se smatra
parnim

self.each do |object|
if isEven
wasABlock_nowAProc.call object
end

isEven = (not isEven) # Praviti razliku među parnim i neparnim


end
end

end

['apple', 'bad apple', 'cherry', 'durian'].eachEven do |fruit|


puts 'Yum! I just love '+fruit+' pies, don\'t you?'
end

# Upamtite, iz niza uzimamo parne brojeve, a u nizu postoje


# i oni koji to nisu,...samo zato što ja volim praviti probleme.

[1, 2, 3, 4, 5].eachEven do |oddBall|


puts oddBall.to_s+' is NOT an even number!'
end

Ispis:
Yum! I just love apple pies, don't you?
Yum! I just love cherry pies, don't you?
1 is NOT an even number!
3 is NOT an even number!
5 is NOT an even number!

Da bi proslijedili blok metodi –eachEven-, sve što smo trebali učiniti je zalijepiti taj blok nakon metode.
Na ovaj način možete zalijepiti bilo koji blok koda, iako će većina metoda jednostavno ignorisati blok. Da
se to ne bi desilo, nego da bi metoda „prigrabila“ blok i pretvorila ga u proceduru, postavite ime te
procedure na kraj liste parametara vaše metode, stavljajući ispred imena znak (&). Taj dio je malo
zamršen, ali ne i previše, obzirom da ga je potrebno uraditi samo jednom, na početku, pri definisanju
metode. Nakon toga možete tu metodu koristiti onoliko puta koliko poželite, baš kao i neke integrisane
metode,...kao što su –each- ili –times- (sjećate li se 5.times do?)

Ako se zbunite na momenat, pomislite samo što bi eachEven trebalo da učini: pozove proslijeđeni blok
koda za svaki od elemenata u nizu. Nakon što ste je (metodu) napisali i uvjerili se da radi, nije potrebno da
razmišljate šta se dešava „pod haubom“ (koji blok se kada poziva??); ustvari, to je upravo razlog zbog
kojeg pišemo metod na ovaj način: da ne bismo morali misliti na koji način one rade. Jednostavno, mi ih
samo koristimo.

Sjećam se da sam pokušavao vidjeti koliko traju pojedini dijelovi programa (što još poznato i kao
profiliranje koda). Tako sam napisao metodu koja mjeri vrijeme prije izvršavanja koda, onda ga izvršava, a
nakon toga ponovo mjeri vrijeme na kraju i ispisuje razlike. Trenutno ne mogu pronaći taj kod, ali mi
trenutno i ne treba; vjerovatno je ličio na nešto ovako:

-67-
def profile descriptionOfBlock, &block
startTime = Time.now

block.call

duration = Time.now - startTime

puts descriptionOfBlock+': '+duration.to_s+' seconds'


end

profile '25000 doublings' do


number = 1

25000.times do
number = number + number
end

puts number.to_s.length.to_s+' digits' # That is, the number of digits


in this HUGE number.
end

profile 'count to a million' do


number = 0

1000000.times do
number = number + 1
end
end

Ispis:
7526 digits
25000 doublings: 1.06135 seconds
count to a million: 0.84302 seconds

Kako je samo jednostavno! Elegantno! Ovom malom metodom, mogu izmjeriti vrijeme između pojedinih
odjeljaka bilo kojeg programa. Jednostavno ubacim kod u blok i pošaljem ga na profiliranje. Ima li šta
jednostavnije? U većini programskih jezika, morao bih eksplicitno dodati kod za mjerenje vremena za svai
dio programa kojemu sam želio izmjeriti vrijeme. U Ruby, međutim, sve je ne jednom mjestu i što je još
važnije – nije mi na putu!

Par stvarčica za oprobati


 „Đedov sahat“. Napravite metodu koja uzima blok koda i poziva ga svaka četiri sata u jednom
danu. Naprimjer, ako bismo proslijedili blok „do puts 'DONG!' end“, program bi vratio neku vrstu
alarma (klinga), kao djedov stari sat. Testirajte svoj kod sa par različitih blokova (uključujući i ovaj
koji sam vam dao). Caka: možete iskoristiti Time.now.hour da dobijete trenutno vijeme (sat).
Međutim, ova metoda će vam vratiti broj između 0 i 23, tako da ćete morati izmijeniti te vrijednosti
da biste dobili standardne vrijednosti koji ima jedan zidni sat,...stari „Đedov sahat“ (1-12).
  „Bilježnik programa“ Napišite metodu koju ćete nazvati –log-, koja daje tekstualni ispis koji
opisuje blok koda na kome trenutno radi; slično metodi doSelfImportantly, trebao bi redati
stringove koji nam govore kad počne jedan blok, a kad završava, te uz to šta je i povratna vrijednost
bloka. Testirajte svoju metodu tako što ćete joj poslati blok nekog koda. Unutar bloka, pozovite se
-68-
još jednom na -log- proslijeđujući i njemu novi blok (ovakav način integrisanja koda se naziva
„gnježdenje“). Drugim riječima, ispis bi trebao izgledati otprilike ovako
Beginning "outer block"...
Beginning "some little block"...
..."some little block" finished, returning: 5
Beginning "yet another block"...
..."yet another block" finished, returning: I like Thai food!
..."outer block" finished, returning: false
 “Bolji bilježnik”. Ispis koji je imao prošli program je nekako težak za razumjeti i što bi ga više
koristili, bivalo bi sve gore. Bilo bi ga daleko bolje shvatiti ako bi se nekako sortirale linije koda
tako da možemo razlikovati unutrašnje i vanjske blokove. Da bismo postigli ovo, trebaće nam
globalne varijable, one koje možemo vidjeti/pristupiti im u bilo kojem dijeu koda. Globalne
varijable se definišu tako da ispred njihovog imena postavimo zna ($), kao npr. $global,
$nestingDepth... Na kraju, bilježnik bi trebao dati ispis sličan ovome: Beginning "outer block"...
Beginning "some little block"...
Beginning "teeny-tiny block"...
..."teeny-tiny block" finished, returning: lots of love
..."some little block" finished, returning: 42
Beginning "yet another block"...
..."yet another block" finished, returning: I love Indian food!
..."outer block" finished, returning: true

Dobro, to bi bilo sve što ćemo naučiti u ovom tutorialu. Čestitam! Dosta ste naučili! Moguće je da ćete
trenutno osjećati da se baš svega i ne sjećate, ili da ste određene dijelove preskočili...ali to nema veze,
stvarno! Ne radi se u programiranju o tome šta ste zapamtili i šta od toga znate, nego se radi o tome šta
možete „skontati“. Sve dok možete i znate gdje naći stvari koje ste zaboravili, ne morate se puno brinuti.
Nadam se da ne mislite da sam sve ovo napisao ne gledajući uvijek na poglavlja iza i podsjećajući sebe na
neke stvari koje sam zaboravio! Zato što jesam – stalno sam se vraćao na prethodna poglavlja. Dosta mi je
pomogao i kod koji je dio ovog tutoriala, kod u vidu primjera. A sad pogledajte gdje sam to ja sve tražio
ono što sam na trenutak zaboravio ili gdje sam tražio pomoć kad mi je trebala.

11. Izvan ovog tutoriala


Gdje ćemo to sad? Ako imate kakvih pitanja, kome da ih postavite? Šta ako poželite da vaš program otvori
web stranicu ili pošalje e-mail ili promjeni dimenzije digitalne fotografije. E pa, postoji mnogo, mnogo,
različitih mjesta gdje možete naći pomoć, kad je Ruby u pitanju. Nažalost, to nekako i ne zvuči kao velika
pomoć, zar ne? ;-)

Za mene postoje tri mjesta na kojima sam siguran da ću pronaći pomoć za Ruby. Ako je neka sitnica u
pitanju i mislim da mogu sam eksperimentisati i pronaći odgovor onda koristim IRB. Desi li se da je
pitanje nešto malo složenije, pa treba kopati malo dublje, onda koristim vlastitu „krampu“. Međutim, ako
se desi da ni to ne pomaže onda fino pristupim na ruby-talk.

IRB: interaktivna Ruby


Kad je na vaš sistem instalirana Ruby, u tom paketu se nalazi i irb – njena interaktivna konzola. IRB je
jednostavno pokrenuti, na način da u komandni prompt [k.p.: važi i za Linux i za Windows OS] upišete irb
[+Enter]. Kad ste u irb-u možete upisati bilo koji izraz i Ruby će vam vratiti vrijednost koja je njegov
rezultat. Upišite 1 + 2 i irb vraća rezultat 3 (ne morate čak koristiti puts). Kad završite, jednostavno upišite
„exit“.

-69-
Nije ovo sve što irb pruža, ali ostatak možete naučiti koristeći moju „krampu“.

KRAMPA: „Programming Ruby“


Knjiga koju morate imate je „Programming Ruby, The Pragmatic Programer's Guide“, koju su napisali
David Thomas i Andrew Hunt (Pragmatični programeri). Iako ćete se dobro snaći i sa starijom verzijom,
toplo vam preporučujem drugo izdanje ove sjajne knjige, jer ona pokriva poslijednju verziju Ruby. Stariju
verziju možete dobiti i besplatno, putem interneta, a uz Ruby na Windows-ima trebalo bi da knjiga
standardno dolazi.

Možete u njoj naći baš sve o Ruby, od početničkog do naprednog. Lahka je za čitanje, razumljiva, ma
jednostavno savršena! Kamo sreće da svaki programski jezik ima ovako kvalitetnu knjigu kakva je ova. Na
poleđini knjige ćete naći ogromnu zbirku koja opisuje do detalja svaku metodu i svakoj klasi, sve
potkovano primjerima. Ma ja jednostavno volim ovu knjigu!

Nekoliko je adresa preko kojih je možete preuzeti (uključujući i stranicu Pragmatičnih programera), ali
meni omiljeno mjesto je ruby-doc.org. Verzija postavljena na toj stranici ima lijepo predočen sadržaj i
dobar indeks (a pored toga ima odličnu dokumentaciju koja pokriva sve što se može dovesti u vezu s
Ruby).
Zašto sam je nazvao „krampa“? Pa, na naslovnoj strani je nacrtana krampa...možda je smiješno ime.
Ruby-Talk: mailing lista za Ruby
Ponekad čak i uz irb i "krampu" ne može se naći riješenje za određeni problem. Ili možda želite znati da li
je neko prije vas to uradio, tako da vi to ne morate. Ruby-Talk je u tom slučaju prava adresa. Lista je puna
prijateljski nastrojenih, pametnih ljudi, koji su spremni pomoći. Više detalja o njoj ovdje.
Tim Toady
Nešto od čega sam vas pokušao zaštiti, ali na što ćete svakako naletiti uskoro, jeste koncept TMTOWTDI
(izgovara se kao "Tim Toady"): There's More Than One Way To Do It – postoji više od jednog načina da
se to uradi.

Neki će reći da je taj koncept prava stvar, dok će drugi dati drukčije mišljenje. Ja lično nešto plaho i ne
volim ovaj koncept jer je to užasan način da se nekoga podučava programiranju. (Kao da i ovaj jedan način
nije dovoljno izazovan i ponekad zbunjujući.)

Međutim, sad kada idete izvan ovog tutoriala, vjerovatno ćete vidjeti mnogo različitih postavki koda za
jedan te isti programerski problem. Naprimjer, mogu smisliti najmanje pet različitih načina da ispišem
string, na način drukčiji od pukog zarobljavanja među navode, a svaki od njih radi na drukčiji način. Šest
najjednostavnijih sam vam već pokazao.

Kad smo pričali ogrananju, pokazao sam vam –if- ali nisam –unless-. Pustiću vas da sami „skontate“
njegovu svrhu koristeći irb.

Još jedna fina „prečica“ koju možete koristiti uz –if-, -unless- i –while- je:

# Ovo su riječi iz programa koji sam napisao, a koji


# generiše riječi na jeziku nalik na engleski. Cool, huh?
puts 'grobably combergearl kitatently thememberate' if 5 == 2**2 + 1**1
puts 'enlestrationshifter supposine follutify blace' unless
'Chris'.length == 5

Ispis:
grobably combergearl kitatently thememberate

Konačno, postoji još jedan način da se napišu metode koje „gutaju“ blokove koda (a ne procedure). Vidjeli
-70-
smo da smo u jednom primjeru zgrabili blok koda i pretvorili ga u proceduru koristeći &block caku u listi
parametara, pri definiciji funkcije. Onda, da bi pozvali taj blok na izvršenje, jednostavno smo dali komandu
block.call. E pa, postoji i kraći način da se to učini (iako ga ja lično smatram zbunjujućim). Umjesto
ovoga:

def doItTwice(&block)
block.call
block.call
end

doItTwice do
puts 'murditivent flavitemphan siresent litics'
end

Ispis:
murditivent flavitemphan siresent litics
murditivent flavitemphan siresent litics

...napišemo slijedeće:

def doItTwice
yield
yield
end

doItTwice do
puts 'buritiate mustripe lablic acticise'
end

Ispis:
buritiate mustripe lablic acticise
buritiate mustripe lablic acticise

Ne znam, baš,...šta vi mislite? Možda je samo do mene, ali...YIELD!? Da je bilo nešto kao
call_the_hidden_block, ili nešto njemu slično, meni bi imalo više smisla. Mnogo ljudi kaže da YIELD
njima ima smisla. Ha, valjda je to sva poenta TMTOWTDI: oni će raditi kako im volja, a ja kako je meni.

KRAJ
Iskoristite ovo znanje u korisnu svrhu, a ne za kakvo zlo! :-) Svakako, ako vam je ovaj tutorial bio od
pomoći (ili vas je dodatno zbunio, ili nađete grješku), javite mi na e-mail!
#. Appendix
Ovo dio je namijenjen za izradu zadataka koji se nalaze u tutorialu. Nakon što ih propisno testiram u Ruby,
biće objavljeni. Ukoliko imate pitanje ili želite obavješteni kada oni budu postavljeni kontaktirajte me na
info u komentaru:

-71-

You might also like