FIGYELEM! Ez a dokumentum kizárólag az ELTE IK hallgatók számára oktatási célra készült! Félkész munka, dolgozunk rajta! Terjeszteni, felhasználni máshol a szerzők engedélye nélkül tilos!

Ruby.new


Eredetileg (még fiatalok voltunk) amikor ezt a könyvet írtuk, volt egy nagy tervünk. Le akartuk dokumentálni az egész nyelvet tetőtől talpig kezdve az osztályoktól és objektumoktól az egészen apró részletekig. Ez először nagyon jó ötletnek tűnt. Mivel a Ruby-ban majdnem minden objektum, így célszerű először erről beszélni.

Illetve mi így gondoltuk.

Aztán kiderült, hogy ez kissé bonyolult módja egy nyelv leírásának. Ha még nem beszéltél stringekről, if utasításokról, értékadásokról és más részletekről, kissé problémás osztály példákat írni. Miközben végighaladtunk leírásunkban fentről lefele, érinteni fogunk alacsony szintű részleteket is. Annyira, amennyire a példák megértésére szükség van.

Így kiötöltünk egy másik grandiózus tervet (nem véletlenül hívnak minket pragmatikusoknak). Továbbra is fentről kívánjuk a Ruby leírását kezdeni. De mielőtt nekivágnánk, adunk egy rövid fejezetet, melyben általános nyelvi tulajdonságok találhatóak példákon keresztül ismertetve, a Ruby nyelvezetében fogalmazva. Ez egyfajta minitutoriál, mely megadja a kezdő löketet a könyv maradék részének elolvasásához.

A Ruby objektum-orientált nyelv

Mondjuk el mégegyszer. A Ruby egy egyedülálló objektum-orientált nyelv. Bármi, amit használunk, de azok eredménye is objektum. Habár más nyelvek is ugyanezt állítják magukról, más módon értelmezik, mi is az objektum-orientáltság és egy más terminológiát az általuk használt fogalmakra.

Így mielőtt túl messze jutnánk a részletekben, lássuk röviden az általunk használandó kifejezéseket és jelöléseket.

Amikor objektum-orientált kódot írunk, normális esetben a valóságból keresünk modellt a programunkhoz. A modellezés folyamán tipikusan azokat a dolgokat kategorizáljuk, melyeket reprezentálni akarunk kódunkban. Egy zenegép esetében a dal egy kategorizálandó fogalom. Ruby-ban ezeket az entitásokat osztály definiálásával reprezentáljuk. Az osztály állapotok (pl. a dal neve) és metódusok (dal lejátszása) összessége.

Ha az osztályok készen vannak, szeretnénk példányosítani őket. A Song nevű osztályt tartalmazó pénzbedobós zenegépnél szeretnénk külön-külön példányokat olyan népszerű slágerekkel, mint "Ruby Tuesday", "Enveloped in Python", "String of Pearls", "Small talk" és mások. Az objektum szó felváltva használható az osztály példánnyal (mivel gyenge típusosan programozunk, valószínűleg az objektumot használjuk gyakrabban).

Ruby-ban ezek az objektumokat konstruktorral hozzuk létre, amely osztályhoz rendelt speciális metódus. A standard konstrukor neve new.

song1 = Song.new("Ruby Tuesday")
song2 = Song.new("Enveloped in Python")
# és így tovább ..

Mindkét a példány ugyanabból az osztályból van származtatva, azonban saját karakterisztikájuk van. Először is minden objektumnak saját azonosítója van (object identifier, rövidítve object id). Másodszor, definiálhatunk példány változókat, azaz olyan változókat, melyek minden példányra nézve egyedi. Ezek tárolják az objektum állapotát. Esetünkbe Dalaink nagy valószínűséggel tartalmaznak olyan példány változót, mely a dal nevét tárolja.

Oszályokban definiálhatunk példány metódusokat is. Minden metódus egy darabka funkcionalitás, program blokk, mely hívható osztályon belülről és kívülről egyaránt, függően a láthatósági szabályoktól. Ezek a metódusok azonban elérhetik az objektum példány változóit, tehát az objektum állapotát.

Metódusokat objektumnak történő üzenetküldéssel tudunk meghívni. Az üzenet tartalmazza a metódus nevét és a szükséges paramétereket (A metódus hívások üzenetküldéses formája a Smalltalktól ered). Amikor az objektum megkap egy üzenetet, megkeresi az annak megfelelő metódust. Ha megtalálta, végrehajtja, ha viszont nem, akkor ... erre még visszatérünk később.

A metódusok és üzenetek ilyen formája talán komplikáltnak tűnik, gyakorlati szempontból ez nagyon is természetes. Nézzünk meg néhány metódus hívást (a nyilak a kifejezés végén csak a kiértékelések végeredményét mutatják).

"gin joint".length
»	9
"Rick".index("c")
»	2
-1942.abs
»	1942
sam.play(aSong)
» "duh dum, da dum de dum ..."

A pont előtt áll a fogadó objektum, utána pedig a meghívandó metódus neve. Az első példában lekérdeztük egy string hosszát, a másodikban egy a "c" betű pozícióját egy másik stringben. A harmadik páldában egy szám kiszámolja saját abszolút értékét. Végezetül megkérjük Samet, játsszon el egy nótát.

Érdemes itt megjegyezni egy fontos különbséget a Ruby és más nyelvek között. Mondjuk a Javában az abszolút értéket kiszámító függvény egy különálló függvény, melynek paramétere a szám. Ezt így lehetne írni:

number = Math.abs(number)
// Java code

Ruby-ban az abszolút érték kiszámítás képessége a számokba van beépítve. Csak elküldjük az abs üzenetet nekik, a munkát pedig rájuk hagyjuk.

number = number.abs

Ugyanez igaz minden Ruby objektumra. C nyelven ezt írnánk: strlen(name), Ruby-ban ez name.length, és így tovább. Ez az a része a Ruby-nak, amiért mi valódi objektum-orientált nyelvnek nevezzük.

Néhány alapvető Ruby

Nem sok ember szeret rakás unalmas szintaxis szabályt olvasni, amikor új nyelvet sajátít el. Akkor most csalni fogunk. Ebben a fejezetben érinteni fogunk néhány fontos dolgot, amit egyszerűen ismerni kell, ha Ruby program írásába fogunk. Később, a 18. fejezetben majd elővesszük az összes lényeges részletet.

Mindjárt kezdjük is egy egyszerű Ruby programmal. Írni fogunk egy metódust, ami egy személynevet tartalmazó stringet ad vissza. Ezt aztán párszor meghívjuk.

def sayGoodnight(name)
  result = "Goodnight, " + name
  return result
end
# Time for bed...
puts sayGoodnight("John-Boy")
puts sayGoodnight("Mary-Ellen")

Néhány általános észrevétel: a Ruby szintaxisa tiszta. Nincs szükség utasítások végén pontosvesszőre, legalábbis addig, amíg minden utasítás külön sorba kerül. Ruby kommentek #-kal kezdődnek és a sor végéig tartanak. A kód elrendezése teljesen rajtad múlik, a behúzásnak itt nincs jelentősége.

A metódusokat def kulcsszóval kezdjük, ezt a metódus neve követi (ebben az esetben sayGoodnight.) és a paraméterek zárójelek között. A Ruby nem használ zárójeleket programblokkok, összetett utasítások és definíciók határolásához. Ehelyett a blokk végére end kulcsszó kerül. Metódusunk blokkja igen egyszerű. Az első sor ősszefűzi a "Goodnight," stringet a name paraméterrel, majd ezt értékül adja a result lokális változónak. A második sor visszaadja értéknek a result értékét. Megjegyezzük, hogy a result változót nem kellett deklarálnunk, az egyszerűen létrejött az első értékadáskor.

Miután metódusunkat definiáltuk, meghívjuk kétszer. Mindkét esetben az eredményt a puts metódusnak adjuk át, amely egyszerűen kiírja azt a kimenetre soremeléssel együtt.

Goodnight, John-Boy
Goodnight, Mary-Ellen

A puts sayGoodnight("John-Boy") sor két metódus hívást tartalmaz, az egyik a sayGoodnight, a másik pedig a puts. Miért van az egyik metódus hívás paramétere zárójelben és miért nincs a másik? Ez tisztán csak ízlés kérdése. A következő sorok ekvivalensek egymással.

puts sayGoodnight "John-Boy"
puts sayGoodnight("John-Boy")
puts(sayGoodnight "John-Boy")
puts(sayGoodnight("John-Boy"))

Habár az élet nem mindig ilyen egyszerű, a precedencia szabályok megnehezíthetik annak eldöntését, melyik argumentum melyik metódus hívás paramétere, így mi azt javasoljuk, hogy mindig használjunk zárójelezést a legegyszerűbb esetek kivételével.

Ez a példa tartalmazott néhány Ruby stringet. Több módja is van stringek létrehozásának, de talán a leggyakoribb a string literálok használata: karaktersorozatok aposztrófok (!) vagy idézőjelek (") közé zárva. A kettő között csak az a különbség, ahogy a Ruby feldolgozza őket stringgé. Az aposztrófokkal határolt karakterekkel dolgozik a legkevesebbet. Néhány kivételtől eltekintve amit megadtunk string literálnak, az lesz a string értéke.

A Ruby-nak az idézőjelekkel határolt literálokkal már több a dolga. Első lépésben megkeresi a helyettesítő kifejezéseket - "\" karakterrel kezdődő sorozat - és kicseréli néhány bináris értékkel. A leggyakoribb ilyen például a "\n", amely új sor karakterrel lesz kicserélve. Ha ilyet tartalmazó string kerül a kimenetre, "\n" sortörést eredményez.

puts "And Goodnight,\nGrandma"

a következőt eredményezi:

And Goodnight,
Grandma

A második dolog, amit a Ruby az idézőjelek közé zárt stringgel tesz, az a kifejezés interpoláció. A stringen belül található #{kifejezés} sorozatok kicserélődnek azok értékére. Ezt fel tudjuk előző metódusunk átírására használni.

def sayGoodnight(name)
  result = "Goodnight, #{name}"
  return result
end

Amikor a Ruby létrehozza ezt a string objektumot, veszi a name aktuális értékét és behelyettesíti azt a stringbe. Tetszőlegesen összetett kifejezéseket #{...} formában írjuk, de lehetőség van egyszerűsítésre is. A zárójelek elhagyhatók, ha globális, példány vagy osztály változót használunk. Stringekről és további standard típusokról bővebben az 5. fejezetben olvashatunk.

Végezetül a metóduson is tudunk egyszerűsíteni. Ruby metódus visszatérő értéke az utoljára kiértékelt kifejezés értéke, így megspórolhatjuk a return utasítást.

def sayGoodnight(name)
  "Goodnight, #{name}"
end

Azt ígértük, ez a fejezet rövid lesz. Azonban van még egy témánk: Ruby elnevezések. A rövidség kedvéért használni fogunk néhány olyan terminust (pl. osztály változó), amit még nem definiáltunk. Azonban azzal, hogy most elmondjuk a szabályokat, később csak könnyebb lesz megérteni a példány változókat és más hasonló fogalmat, amikor odaérünk.

Ruby a következő szabályt használja az elnevezések megkülönböztetésére: az első karakter dönti el, hogyan lesz használva az adott név. Lokális változók, metódus paraméterek és metódus nevek mind kisbetűvel vagy aláhúzással kezdődnek. A globális változók dollár ($) jellel, a példány változók kukac (@), az osztály változók pedig dupla kukac (@@) jellel kezdődnek.

Ettől kezdődően a nevek tetszőleges kombinációi lehetnek betűknek, számoknak és aláhúzás jelnek, azzal a kikötéssel, hogy @ jel után szám nem állhat.

Változók Konstansok és
Lokális Globális Példány Osztály osztály nevek
name $debug @name @@total PI
fishAndChips $CUSTOMER @point_1 @@symtab FeetPerMile
x_axis $_ @X @@N String
thx1138 $plan9 @_ @@x_pos MyClass
_26 $Global @plan9 @@SINGLE Jazz_Song

Tömbök és hash táblák

A Ruby tömbök és hash táblák indexelt sorozatok, azaz elemeit kulccsal címezzük. Tömbök esetében az elem sorszáma a kulcs, hash táblák esetében viszont bármilyen objektum lehet. Ráadásul mindketten dinamikusak, azaz új elem bekerülése esetén ha szükséges, növekszik méretük. Tömb elemek hozzáférése hatékonyabb, a hash tábla viszont rugalmasabb. Minden egyes tömb és hash tábla tetszőleges típusú objektumot tartalmazhat, lehet benne egészértékű szám, string, lebegőpontos szám, de ezt hamarosan látni fogjuk.

Tömböt létrehozhatunk tömb literál segítségével (elemek sorozata szögletes zárójelek közé zárva). Az így megadott tömb objektum elemeit a tömb neve után szögletes zárójelbe írt sorszám segítségével címezzük meg, ahogy ezt a következő példa is mutatja.

# három elemű tömb
a = [ 1, 'cat', 3.14 ]
# első elem
a[0]
» 1
# értéket adunk a harmadik elemnek
a[2] = nil
# kiírjuk a tömböt
a
» [1, "cat", nil]

Üres tömböt létrehozhatunk akár tömb literállal, akár a tömb osztály konstruktorával: Array.new

empty1 = []
empty2 = Array.new

Néha nagy kinlódás olyan tömböt létrehozni, mely szavai vesszőket, idézőjeleket tartalmaznak. Szerencsére erre is létezik egy segítség, a %w rövidítés:

a = %w{ ant bee cat dog elk }
a[0]
» "ant"
a[3]
» "dog"

A Ruby hash táblák hasonlóak a tömbhöz. Hash literál kapcsos zárójeleket használ, közöttük pedig kulcs-érték párok vannak felsorolva.

Például ha hangszerekhez szeretnénk zenekari szekciót rendelni, azt hash táblával tudjuk megtenni:

instSection = {
  'cello'     => 'string',
  'clarinet'  => 'woodwind',
  'drum'      => 'percussion',
  'oboe'      => 'woodwind',
  'trumpet'   => 'brass',
  'violin'    => 'string'
}

Hash táblák ugyanúgy szögletes zárójelekkel címezhetőek, mint a tömbök.

instSection['oboe']
» "woodwind"
instSection['cello']
» "string"
instSection['bassoon']
» nil

Ahogy utolsó példánkban láthattuk, hash tábla nil-t ad vissza, ha olyan kulccsal címezzük meg, amit nem tartalmaz. Ez teljesen jó nekünk, mert a nil üres érték feltételes kifejezéseknél false-t, hamis választ jelent. Azonban előfordulhat, hogy a hash tábla ezen viselkedést szeretnénk megváltoztatni. Ha például arra használnánk hash táblát, hogy minden egyes előforduló kulcsot megszámoljunk, akkor célszerű ezt az alapértéket nullára állítani, melyet könnyedén megtehetünk azzal, hogy a new konstruktor paramétereként 0-t adunk.

histogram = Hash.new(0)
histogram['key1']
» 0
histogram['key1'] = histogram['key1'] + 1
histogram['key1']
» 1

A tömb és hash tábla objektumoknak sok hasznos funkciójuk van még: lásd a 33. oldalon és a referenciában!(?)

Vezérlési szerkezetek

A Ruby rendelkezik minden szokásos vezérlési szerkezettel mint pl. if elágazással vagy while ciklussal. Java, C és Perl programozók biztosan meghökkennek azon, hogy az utasítás blokk körül hiányzanak a zárójelek. A Ruby az end kulcsszót használja a blokk vége jelzésére.

if count > 10
  puts "Try again"
elsif tries == 3
  puts "You lose"
else
  puts "Enter a number"
end

Hasonló módon end-del végződik a while utasítás is.


while weight < 100 and numPallets <= 30
  pallet = nextPallet()
  weight += pallet.weight
  numPallets += 1
end

A Ruby utasítás módosítók igen hasznos kiegészítők, ha az if vagy while törzse csak egy kifejezés. Egyszerűen írjuk le a kifejezést a végén if vagy while kulcsszóval mögötte a feltétellel. Itt egy példa egyszerű if-re

if radiation > 3000
  puts "Danger, Will Robinson"
end

Ugyanez rövidebben:

puts "Danger, Will Robinson" if radiation > 3000

Hasonló módon egy while ciklus

while square < 1000
  square = square*square
end

rövidebb így írva:

square = square*square  while square < 1000

Ezek a módosítók biztosan ismerősek Perl programozók számára.

Reguláris kifejezések

A legtöbb beépített Ruby típus ismerős lesz minden programozónak. A nyelvek többsége rendelkezik stringgel, lebegőpontos számokkal, tömbökkel és így tovább. Habár amíg a Ruby meg nem jelent, beépített reguláris kifejezés támogatás általában csak az úgynevezett szkript nyelvekben létezett (Perl, Python, awk). Ez hiba. A reguláris kifejezések, még ha titokzatosan is néznek ki, nagyon hatékony eszközök szöveg feldolgozásra.

Egész könyveket töltenek meg reguláris kifejezésekről írva, így nem fogunk minden részletre kitérni külön. Helyette megnézünk néhány példát arra, hogyan működnek a reguláris kifejezések.

A reguláris kifejezés semmi más, mint egyszerűen egy karakterekből álló minta, melyet stringhez akarunk illeszteni. Reguláris kifejezést Ruby-ban tipikusan per jelek közé írt karakterekkel adunk meg (/egy_minta/). És mivel a Ruby-ban vagyunk, természetesen a reguláris kifejezések is objektumok, melyekkel hasonló módon kell bánni, mint más objektumokkal.

A példa kedvéért, ha olyan mintát szeretnél, amely illeszkedik a "Perl" vagy "Python" szavakra, a következő reguláris kifejezés megteszi ezt:

/Perl|Python/

Per jelek határolják körbe a mintát, mely tartalmazza a két illesztendő stringet függőleges vonallal ("|", angolul: pipe) szétválasztva. Az aritmetikai kifejezésekben is használt zárójelezést itt is használhatjuk, így átírva a kifejezést, az alábbi módon fog kinézni:

/P(erl|ython)/

Mintán belül megadhatunk ismétlődéseket is. /ab+c/ minta minden olyan stringre illeszkedik, amely "a" betűvel kezdődik, egy vagy több "b"-t tartalmaz és "c"-re végződik. Ha a plusz jelet kicseréljük csillagra, akkor a /ab*c/ minta hasonló stringekre fog illeszkedni azzal a különbséggel, hogy azok semmi vagy több "b"-t tartalmazhatnak.

Illeszthetünk továbbá karakterek egy csoportjára is mintán belül. Közismert példa erre olyan karakter osztályok, mint a \s, amely tetszőleges helykitöltő (whitespace) karakterre illeszkedik (szóköz, tabulátor, új sor, stb.), a \d osztály, amely számjegyekre és a \w osztály, amely tipikusan szavakban előforduló betűkre illeszkedik. A . (pont) speciálisan tetszőleges karakterre illeszkedik.

Ezek segítségével könnyedén összeüthetünk hasznos reguláris kifejezéseket.

/\d\d:\d\d:\d\d/     # időpont, pl. 12:34:56
/Perl.*Python/       # Perl, nulla vagy több karakter, majd Python
/Perl\s+Python/      # Perl, egy vagy több szóköz, majd Python
/Ruby (Perl|Python)/ # Ruby, szóköz majd vagy Perl vagy Python

Ha egyszer létrehoztunk egy reguláris kifejezés mintát, hiba lenne nem használni. A =~ operátor segítségével illeszthetünk reguláris kifejezéseket stringekre. Ha ez illeszkedik, az operátor annak kezdő pozícióját adja vissza, egyébként nil-t. Ez azt jelenti, hogy kifejezéseinket használhatjuk if és while utasítás feltételeként. Például a következő kódrészlet üzenetet ír ki a kimenetre, ha egy adott string tartalmazza a 'Perl' vagy 'Python' szavakat:

if line =~ /Perl|Python/
  puts "Scripting language mentioned: #{line}"
end

A string illeszkedő része kicserélhető másra. Erre van a Ruby-nak egy helyettesítő eljárása.

line.sub(/Perl/, 'Ruby')    # replace first 'Perl' with 'Ruby'
line.gsub(/Python/, 'Ruby') # replace every 'Python' with 'Ruby'

Még sok mindent el fogunk mondanunk a reguláris kifejezésekről, ahogy végighaladunk a könyvön.

Blokkok és iterátorok

Ez a fejezet rövid leírást foglal magában a Ruby nyelv egyik erősségéről. Mi most a kód blokkokra, mint olyan kódrészletekre tekintünk, amelyek kvázi paraméterként metódushíváshoz társíthatók. Ez egy hihetetlenül erős tulajdonsága a Ruby-nak. A blokkok hasznosíthatóak callback-ként (visszahívás), továbbadott kódrészletként vagy iterátor létrehozásához.

A kód blokkok egyszerűen csak do...end közé zárt utasítások.

{ puts "Hello" }       # Ez egy blokk
do                     #
  club.enroll(person)  # és ez is
  person.socialize     #
end                    #

Egy így elkészített kód blokkot máris metódushíváshoz társíthatjuk. Ez a metódus ezután meg fogja tudni hívni a társított kód blokkot egyszer vagy többször is. Kód blokkot a yield utasítással hívhatunk meg. A következő példa ezt mutatja meg működés közben. Definiálunk egy metódust, amely kétszer hívja meg a yield-et. Ezt a metódust fogjuk mi meghívni egy blokkal kiegészítve.

Megjegyzés: sokan úgy vélik, a blokk társítás is egyfajta paraméter átadás. Ugyan egy szinten működik azzal, ez mégis másik történet. Célszerűbb a blokkra, mint társrutinra gondolni, amely időnként megkapja a vezérlést, majd visszaadja.

def callBlock
  yield
  yield
end
callBlock { puts "A blokkban" }

ezt eredményezi:

A blokkban
A blokkban

Nézzük meg, ahogy a blokkon belüli kód (puts "A blokkban") a yield paranccsal hívásra kerül kétszer is.

A yield-nek paramétereket is adhatunk, melyek átadódnak a blokknak. A paraméter neveket a kód blokkon belül függőleges vonalak között ("|") felsorolva adjuk meg.

def callBlock
  yield ,
end
callBlock { |, | ... }

A Ruby könyvtár számos helyen alkalmazza a kód blokkokat iterátorok létrehozásához. Az iterátor olyan speciális operátor, amely az adott adatszerkezet (pl. tömb) bejárásával egy elem rákövetkezőjét adja vissza.

a = %w( ant bee cat dog elk )    # tömb létrehozása
a.each { |animal| puts animal }  # a tömb iterálása (bejárása).

A következőt eredményezi:

ant
bee
cat
dog
elk

Most nézzük meg, hogy implementálhatjuk a fenti példában használt each iterátort Array típusú (tömb) adatszerkezethez. Az each végighalad a tömb elemein, egyenként meghívva a yield-et az adott elemmel paraméterezve. Pszeudókódban ez így nézne ki.

# a Array osztályon belül...
def each
  for each element
minden egyes elemre ...
    yield(element)
  end
end

Ezután végigiterálhatjuk a tömb elemeit meghívva annak each metódusát és egy kód blokkot megadva neki. Minden egyes elemmel ez a blokk fog meghívódni.

[ 'macska', 'kutya', 'ló' ].each do |animal|
  print animal, " -- "
end

Ezt eredményezi:

macska -- kutya -- ló --

Ehhez hasonlóan számos ciklikus konstrukció, amelyek C-hez hasonló nyelvekben beépítettek a Ruby-ban egyszerű metódushívások. Ezek a metódusok fogják a ciklusmagot, mint blokkot hívogatni.

5.times {  print "*" }
3.upto(6) {|i|  print i }
('a'..'e').each {|char| print char }

Lefuttatva ezt eredményezi:

*****3456abcde

Itt az 5-ös számot megkértük, hogy futtassa le a melléírt blokkot ötször, a 3-as számot, hogy addig hívja a blokkot a rákövetkező egész számokkal, amíg azok a 3-tól elérnek a 6-ig. Végezetül az a-tól e-ig terjedő betűtartományt iteráljuk az each metódus segítségével.

Írás és olvasás

A Ruby igen széleskörű I/O könyvtárral rendelkezik. Mi viszont példáink többségénél megmaradunk pár egyszerű metódusnál. Eddig már találkoztunk kettővel, melyek kiírnak a kimenetre. A puts kiírja minden argumentumát, majd egy új sor karaktert a végén, a print ugyanezt teszi, viszont új sor karakter nélkül. Mindkét metódus ki tud írni tetszőleges I/O eszközre, alapesetben azonban a standard kimenetre teszik.

Egy másik kiíró metódus, melyet gyakran használunk, a printf. Ez a C vagy Perl nyelvben megszokott formázási string alapján írja ki paramétereit.

printf "szám: %5.2f, szöveg: %s", 1.23, "hello"

Eredménye:

szám:  1.23, szöveg: hello

Ebben a példában a "Number: %5.2f, String: %s" formázási string árulja el a printf számára, hogyan helyettesítse be a lebegőpontos számot (öt egész számjegy plusz két tizedes jegy) és a stringet.

Számos módja van programunknak a bemenet olvasására. Talán a leghagyományosabb mód a gets használata, amely visszaadja a következő beolvasott sort a bemenetről.

line = gets
print line

A gets rutinnak van egy mellékhatása: nemcsak a beolvasott sort adja vissza, hanem azt a $_ globális változóban is eltárolja. Ez a változó speciálisan erre használható. Ha aprintf-et paraméterek nélkül hívja meg, a $_ tartalmát fogja kiírni. Ha az if vagy while parancsok feltételeként reguláris kifejezést adunk meg önmagában, összehasonlító operátor és string nélkül, akkor a kifejezés a $_-hoz illeszkedését fogja vizsgálni. Amíg mi néhány puritán szemében ez bosszantó, ezek a rövidítések segítenek rövid programokat írni. Például a következő program minden olyan bemenetről olvasott sort kiír, amely tartalmazza a "Ruby" szót.

while gets           # assigns line to $_
  if /Ruby/          # matches against $_
    print            # prints $_
  end
end

Ugyanezt még inkább Ruby-s módon megírni iterátor segítségével lehet.

ARGF.each { |line|  print line  if line =~ /Ruby/ }

A fenti kód az ARGF előre definiált objektumot használja, amely a program által olvasható bemenetet reprezentálja.

Előre és felfele

Ennyi az egész. Befejeztük villámgyors kirándulásunkat a Ruby néhány alapvető funkciója körül. Röviden áttekintettük az objektumokat, metódusokat, stringeket, konténereket és reguláris kifejezéseket. Megnéztünk egyszerű vezérlési szerkezeteket és néhány remek iterátort is. Remélhetőleg ez a fejezet adott elég lőszert ahhoz, hogy képesek legyünk a hátralevő fejezeteket letámadni.

Ideje továbblépni, feljebb és feljebb egy magasabb szintre. Következőnek az osztályokat és az objektumokat tekintjük át. Ezek egyszerre a Ruby legmagasabb szintű konstrukciói és az egész nyelv alapvető támaszai.

< Előző oldalKövetkező oldal >