227
#. 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

Ruby Programming

Embed Size (px)

Citation preview

Page 1: Ruby Programming

#. 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

Page 2: Ruby Programming

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 ([email protected])

[http://sites.google.com/site/rubynabosanskom/]

Page 3: Ruby Programming

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.

Page 4: Ruby Programming

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...

Page 5: Ruby Programming

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

Page 6: Ruby Programming

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

Page 7: Ruby Programming

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.

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.

Page 8: Ruby Programming

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

Page 9: Ruby Programming

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

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

© 2003-2009 Chris Pine

Page 10: Ruby Programming

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

Page 11: Ruby Programming

računara, onda već govorimo o nečemu što se u profesiji programera naziva kod. U ovaj sam tutorial uvrstio 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

Page 12: Ruby Programming

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).

Page 13: Ruby Programming

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

Page 14: Ruby Programming

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).

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

Page 15: Ruby Programming

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“).

Page 16: Ruby Programming

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.

Page 17: Ruby Programming

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

© 2003-2009 Chris Pine

http://pine.fm/LearnToProgram/

Page 18: Ruby Programming

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

Page 19: Ruby Programming

„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!

Page 20: Ruby Programming

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:

Page 21: Ruby Programming

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

Page 22: Ruby Programming

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,

Page 23: Ruby Programming

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)?

Page 24: Ruby Programming

koliko ste sekundi stari?

koliko čokolada se nadate da bi mogli pojesti u životu?

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.

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

© 2003-2009 Chris Pine

2. Slova

Dakle, naučili smo ponešto o brojkama, ali šta je sa slovima, riječima, tekstom? Grupu znakova u jednom

Page 25: Ruby Programming

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:

Page 26: Ruby Programming

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)

Page 27: Ruby Programming

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.'

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:

Page 28: Ruby Programming

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:

Page 29: Ruby Programming

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

Page 30: Ruby Programming

puts '12' + '12'

puts '12 + 12'

Ispis:

24

1212

12 + 12

A šta kažete na ovo:

puts 2 * 5

puts '2' * 5

puts '2 * 5'

Ispis:

Page 31: Ruby Programming

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>

Page 32: Ruby Programming

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!'

Page 33: Ruby Programming

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!'

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

Page 34: Ruby Programming

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

Page 35: Ruby Programming

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.

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

© 2003-2009 Chris Pine

http://pine.fm/LearnToProgram/

Page 36: Ruby Programming

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.

Page 37: Ruby Programming

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).

myString = '...you can say that again...'

puts myString

puts myString

Ispis:

...you can say that again...

...you can say that again...

Page 38: Ruby Programming

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!

Page 39: Ruby Programming

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:

Page 40: Ruby Programming

var = 'just another ' + 'string'

puts var

var = 5 * (1+2)

puts var

Ispis:

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

Page 41: Ruby Programming

puts var2

puts ''

var1 = 'eight'

puts var1

puts var2

Ispis:

8

8

eight

8

Page 42: Ruby Programming

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!

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

© 2003-2009 Chris Pine

http://pine.fm/LearnToProgram/

Page 43: Ruby Programming

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.

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.

Page 44: Ruby Programming

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

Page 45: Ruby Programming

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

Page 46: Ruby Programming

'='), 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

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:

Page 47: Ruby Programming

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

Page 48: Ruby Programming

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'

Page 49: Ruby Programming

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 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.

Page 50: Ruby Programming

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

Page 51: Ruby Programming

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?'

Page 52: Ruby Programming

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. :)

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

Page 53: Ruby Programming

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).

Page 54: Ruby Programming

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.

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

© 2003-2009 Chris Pine

http://pine.fm/LearnToProgram/

Page 55: Ruby Programming
Page 56: Ruby Programming

5. Još malo o 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

Page 57: Ruby Programming

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 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

Page 58: Ruby Programming

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

Page 59: Ruby Programming

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

Page 60: Ruby Programming

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

Page 61: Ruby Programming

riječnika. 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

Page 62: Ruby Programming

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

Page 63: Ruby Programming

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?'

Page 64: Ruby Programming

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!?

Page 65: Ruby Programming

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

Page 66: Ruby Programming

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.

Page 67: Ruby Programming

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.

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))

Page 68: Ruby Programming

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

Page 69: Ruby Programming

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:

Page 70: Ruby Programming

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 <--

--> 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

Page 71: Ruby Programming

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. )

Page 72: Ruby Programming

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

Page 73: Ruby Programming

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 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.

Page 74: Ruby Programming

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

Page 75: Ruby Programming

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))

Page 76: Ruby Programming

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

The weatherman said there is a 100% chance of rain, but you can never trust a weatherman.

Page 77: Ruby Programming

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:

Page 78: Ruby Programming

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

Page 79: Ruby Programming

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:

Page 80: Ruby Programming

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

Page 81: Ruby Programming

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“!

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

© 2003-2009 Chris Pine

http://pine.fm/LearnToProgram/

Page 82: Ruby Programming

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:

puts 1 > 2

Page 83: Ruby Programming

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

Page 84: Ruby Programming

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

Page 85: Ruby Programming

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?].

Page 86: Ruby Programming

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'

Page 87: Ruby Programming

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.

Page 88: Ruby Programming

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

Page 89: Ruby Programming

puts 'Your future is... Oh my! Look at the time!'

puts 'I really have to go, sorry!'

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!

Page 90: Ruby Programming

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

Page 91: Ruby Programming

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...

Page 92: Ruby Programming

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

Page 93: Ruby Programming

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

Page 94: Ruby Programming

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

Page 95: Ruby Programming

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:

Page 96: Ruby Programming

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

Page 97: Ruby Programming

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!

Page 98: Ruby Programming

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?)

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

Page 99: Ruby Programming

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.

Page 100: Ruby Programming

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!'

Page 101: Ruby Programming

end

Ispis:

Hello, what's your name?

Katy

Hello, Katy.

What a lovely name!

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

Page 102: Ruby Programming

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

Page 103: Ruby Programming

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.

Page 104: Ruby Programming

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 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].

Page 105: Ruby Programming

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.

Page 106: Ruby Programming

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

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

© 2003-2009 Chris Pine

http://pine.fm/LearnToProgram/

Page 107: Ruby Programming

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:

[]

Page 108: Ruby Programming

[5]

['Hello', 'Goodbye']

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:

Page 109: Ruby Programming

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

Page 110: Ruby Programming

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.

Page 111: Ruby Programming

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“

-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++!'

Page 112: Ruby Programming

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,

Page 113: Ruby Programming

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.

Page 114: Ruby Programming

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

3.times do

puts 'Hip-Hip-Hooray!'

end

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

Page 115: Ruby Programming

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

Page 116: Ruby Programming

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

200.times do

puts []

end

Ispis:

artichoke

brioche

caramel

artichokebriochecaramel

artichoke, brioche, caramel

artichoke :) brioche :) caramel 8)

Page 117: Ruby Programming

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?

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:

Page 118: Ruby Programming

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

Page 119: Ruby Programming

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.

Page 120: Ruby Programming

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

© 2003-2009 Chris Pine

http://pine.fm/LearnToProgram/

Page 121: Ruby Programming

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'

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.

Page 122: Ruby Programming

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

Page 123: Ruby Programming

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".'

Page 124: Ruby Programming

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

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?'

Page 125: Ruby Programming

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.'

Page 126: Ruby Programming

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

Page 127: Ruby Programming

Do you wet the bed?

no way!

Please answer "yes" or "no".

Do you wet the bed?

NO

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

Page 128: Ruby Programming

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

Page 129: Ruby Programming

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...

Page 130: Ruby Programming

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“.)

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

Page 131: Ruby Programming

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.

Page 132: Ruby Programming

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).

Page 133: Ruby Programming

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

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

Page 134: Ruby Programming

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>>

Page 135: Ruby Programming

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

Page 136: Ruby Programming

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 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.

Page 137: Ruby Programming

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)

Page 138: Ruby Programming

[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

Page 139: Ruby Programming

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

Page 140: Ruby Programming

goodAnswer = false

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).

Page 141: Ruby Programming

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...'

Page 142: Ruby Programming

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?

Page 143: Ruby Programming

yes

Do you like eating tamales?

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.

Page 144: Ruby Programming

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.'

Page 145: Ruby Programming

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

Page 146: Ruby Programming

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

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'

Page 147: Ruby Programming

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

Page 148: Ruby Programming

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

Page 149: Ruby Programming

write = left # Koliko jedinica ima za ispisati?

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'

Page 150: Ruby Programming

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

Page 151: Ruby Programming

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

Page 152: Ruby Programming

eighty-eight

ninety-nine

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

Page 153: Ruby Programming

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š? :)

Page 154: Ruby Programming

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)

Page 155: Ruby Programming

# 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

# 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.

Page 156: Ruby Programming

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

Page 157: Ruby Programming

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

Page 158: Ruby Programming

# Sad jednostavno ispišemo/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)

puts englishNumber(101)

puts englishNumber(234)

puts englishNumber(3211)

puts englishNumber(999999)

puts englishNumber(1000000000000)

Page 159: Ruby Programming

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

Page 160: Ruby Programming

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š

Page 161: Ruby Programming

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 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

Page 162: Ruby Programming

bolje programe za što manje vremena. Zato...idemo dalje...

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

© 2003-2009 Chris Pine

http://pine.fm/LearnToProgram/

Page 163: Ruby Programming

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

Page 164: Ruby Programming

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:

Page 165: Ruby Programming

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

time2 = time + 60 # Minuta kasnije.

puts time

puts time2

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.

Page 166: Ruby Programming

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!

Page 167: Ruby Programming

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:

Page 168: Ruby Programming

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|

puts color

end

colorHash.each do |codeType, color|

puts codeType + ': ' + color

end

Page 169: Ruby Programming

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.

Page 170: Ruby Programming

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 –

Page 171: Ruby Programming

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

english

end

end

Page 172: Ruby Programming

# 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!

Page 173: Ruby Programming

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:

Page 174: Ruby Programming

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

Ispis:

Page 175: Ruby Programming

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.

Page 176: Ruby Programming

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:

Page 177: Ruby Programming

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

Page 178: Ruby Programming

puts die.showing

Ispis:

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

Page 179: Ruby Programming

@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

Page 180: Ruby Programming

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

Page 181: Ruby Programming

def showing

@numberShowing

end

end

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

Page 182: Ruby Programming

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

Page 183: Ruby Programming

@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

Page 184: Ruby Programming

def putToBed

puts 'You put ' + @name + ' to bed.'

@asleep = true

3.times do

if @asleep

passageOfTime

end

if @asleep

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

end

end

if @asleep

@asleep = false

puts @name + ' wakes up slowly.'

end

Page 185: Ruby Programming

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

Page 186: Ruby Programming

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

Page 187: Ruby Programming

# Pomjeri hranu iz stomaka u crijevo.

@stuffInBelly = @stuffInBelly - 1

@stuffInIntestine = @stuffInIntestine + 1

else # Umrije nam zmajić od gladi!

if @asleep

@asleep = false

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

Page 188: Ruby Programming

@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

Page 189: Ruby Programming

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.

Page 190: Ruby Programming

Norbert snores, filling the room with smoke.

Norbert wakes up slowly.

You rock Norbert gently.

He briefly dozes off...

...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!

Page 191: Ruby Programming

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

Page 192: Ruby Programming

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

Page 193: Ruby Programming

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.

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-

Page 194: Ruby Programming

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,...

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

© 2003-2009 Chris Pine

http://pine.fm/LearnToProgram/

Page 195: Ruby Programming

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

Page 196: Ruby Programming

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:

Page 197: Ruby Programming

doYouLike = Proc.new do |aGoodThing|

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

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

Page 198: Ruby Programming

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

Page 199: Ruby Programming

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.

Page 200: Ruby Programming

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

goodbye

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

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

Page 201: Ruby Programming

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

Page 202: Ruby Programming

glance = Proc.new do

puts '<glance>'

end

maybeDo wink

maybeDo glance

twiceDo wink

twiceDo glance

Ispis:

<glance>

<wink>

<wink>

<glance>

<glance>

Page 203: Ruby Programming

(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 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

Page 204: Ruby Programming

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

Page 205: Ruby Programming

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!

Page 206: Ruby Programming

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.

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

Page 207: Ruby Programming

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

Page 208: Ruby Programming

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-.

Page 209: Ruby Programming

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

def eachEven(&wasABlock_nowAProc)

isEven = true

Page 210: Ruby Programming

# 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

Page 211: Ruby Programming

# 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

Page 212: Ruby Programming

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

Page 213: Ruby Programming

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:

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

Page 214: Ruby Programming

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

Page 215: Ruby Programming

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).

Page 216: Ruby Programming

„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 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.

Page 217: Ruby Programming

$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

Page 218: Ruby Programming

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.

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

© 2003-2009 Chris Pine

http://pine.fm/LearnToProgram/

Page 219: Ruby Programming

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

Page 220: Ruby Programming

vraća rezultat 3 (ne morate čak koristiti puts). Kad završite, jednostavno upišite „exit“.

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

Page 221: Ruby Programming

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.

Page 222: Ruby Programming

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.

Page 223: Ruby Programming

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 smo da smo u jednom primjeru zgrabili blok koda i pretvorili ga u proceduru koristeći &block caku u listi parametara, pri

Page 224: Ruby Programming

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

Page 225: Ruby Programming

...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

Page 226: Ruby Programming

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.

K R A J

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!

Page 227: Ruby Programming