A mai célünk megtanulni, hogy a következő kifejezés:
Array.new(3) { n += 1; n * 10 }
=>[10, 20, 30]
mit is jelent, hogyan is működik pontosan.
A Ruby fontos nyelvi elemeit jelentik a blokkok, amelyet szinte minden, Ruby-t használó programozó ismer, a kérdés csak csupán az, tudja is hogy hogyan is működik?
Sokak számára rémisztőnek tűnnek, de a blokkok működésének megértése nem igényel bonyolult logikát,
ugyanakkor használatuk nagy segítséget jelenthet bizonyos problémák egyszerű megoldásában.A következőekben példákkal szeretném bemutatni, hogyan használhatjuk a blokkokat Rubyban.
Azt már tudjuk hogyan adhatunk át blokkot egy metódusnak:
Array(1, 2, 3).each() {
# Ez itt egy blokk
}
vagy más formában:
Array(1, 2, 3).each() do # Ez is egy blokk endÉn személy szerint a do end kulcsszavas megadást többsoros, a kapcsos zárójeleket pedig rövid, egy sorban is elférő utasítású blokkok esetében használom.
Vizsgáljuk meg ezek működését kicsit közelebbről:
class MyBlock
def handle_block (2)
puts "A metódus megkapta a vezérlést"
yield (1)
puts "A blokk visszaadta a vezérlést a blokknak"
end
end
MyBlock.handle_block() do puts "A metódus átadta a vezérlést a blokknak" end
Első ízben a metódusunk hívódik meg(1), a (2) yield nyelvi elem szolgál a blokkok 'vezérlésére'.
Amint az látható a metódusokban ezzel tudjuk a program további futását átadni a kapott blokknak,
majd ha az végzett a feladataival újból visszaadja a vezérlést a metódusunknak. Természetesen a yieldet akárhányszor meghívhatjuk a metódusunkban: az mindannyiszor átadja a vezérlést a blokknak, majd visszatér. Most nézzük meg hogyan tudunk paramétereket is átadni a blokkunknak:class MyBlock
def handle_block
puts "A metódus megkapta a vezérlést"
n=1
while(n < 4)
yield(n)
n += 1
end
puts "A blokk visszaadta a vezérlést a blokknak"
end
end
MyBlock.handle_block() { |value| puts value }
=> 1 2 3
A metódus a yield(n) meghívásával ad át paramétereket a blokknak, míg a blokk a |value| kifejezéssel vesz át paramétereket. A blokk esetében tehát a neki átadott paramétereket a || (pipes - csövek) jelek közé kell tennünk, a yield()-t pedig a megfelelő paraméter sorrenddel kell ellátnunk.
De hogyan tudjuk a blokk visszaadott értékét felhasználni. Például tételezzük fel, hogy egy blokk segítségével képezünk értékeket és azok segítségével létrehozzuk az objektum adott attribútumait.
class Szazadok
attr_reader :values
def initialize(size)
n = 0; @ertekek = []
size.times do
n += 1
value = yield(n) (1)
@values << value
end
end
end
Szazadok.new(3){ |n| n.to_s.upper+".század"(2) }
p Szazadok.values => ["1.század","2.század","3.század"]
A lényeg az (1)-sel megjelölt kifejezésnél van, azaz a blokk visszatérő értékét(2) a yield kifejezés(metódus?) visszatérési értéke tartalmazza. Emlékezzünk csak, hogy a Ruby nyelvben egy kódblokk esetében a visszatérési érték mindig a legutolsónak kiértékelt sor visszaadott értéke - ha nem bíráljuk felül egy megfelelő helyre beszúrt return kulcsszóval.
A initialize metódus pedig a neki átadott értékből (3) tudja, hogy hányszor kell a neki átadott blokkot meghívnia.
Természetesen a fenti programot ennél sokkal egyszerűbben is megoldhattuk volna, ezúttal csak a blokkok visszatérési értékének bemutatása volt a fő célom.
Pontosan ez a működés zajlik le, amikor meghívjuk a bejegyzés elején bemutatott példát:
Array.new(3) { n += 1; n * 10 }
=>[10, 20, 30]