Stručně řečeno, Ruby umožňuje vzít blok zdrojového kódu (kódu mezi klíčovými slovy do
a end
), umístit ho do nějakého objektu (nazvaného Proc
), uložit ho v proměnné nebo vložit do metody a spustit tento kus kódu kdekoliv chcete a především kolikrát chcete.
Podobá se to druhu určité metody s rozdílem, že není umístěna v objektu, ale sama o sobě je objektem, který můžete umístit snad kamkoliv.
pozdrav = Proc.new do
puts "Ahoj!"
end
pozdrav.call
pozdrav.call
pozdrav.call
zobrazí
Ahoj!
Ahoj!
Ahoj!
Blokům můžete předávat parametry stejně jako metodám.
mamRad = Proc.new do |dobrota|
puts 'Mam *rad* ' + dobrota + '!'
end
mamRad.call 'pivo'
mamRad.call 'vino'
zobrazí
Mam *rad* pivo!
Mam *rad* vino!
Zatím se to dost podobá metodám tak, je známe, takže pojďme zkusit něco jiného, vložme blok do nějaké metody.
Vkládání bloků do metod
def osloveni rec
puts 'Všichni se prosím ztište, chci vám říct něco důležitého'
rec.call
puts 'Tak to bylo vše, děkuji'
end
ahoj = Proc.new do
puts 'Dobrý den'
end
nashledanou = Proc.new do
puts 'Mějte se pěkně'
end
osloveni ahoj
puts
osloveni nashledanou
zobrazí
Všichni se prosím ztište, chci vám říct něco důležitého
Dobrý den
Tak to bylo vše, děkuji
Všichni se prosím ztište, chci vám říct něco důležitého
Mějte se pěkně
Tak to bylo vše, děkuji
V příkladu jsme vytvořili dva bloky ahoj
a nashledanou
. Vytvořené bloky se zavolají pomocí metody call
.
Metody vracející Proc
Nyní budeme provádět následující "kouzla".
def vypocet proc1, proc2
Proc.new do |x|
proc2.call(proc1.call(x))
end
end
umocnit = Proc.new do |x|
x * x
end
secist = Proc.new do |x|
x + x
end
secistPakUmocnit = vypocet secist, umocnit
umocnitPakSecist = vypocet umocnit, secist
puts secistPakUmocnit.call(5)
puts umocnitPakSecist.call(5)
zobrazí
100
50
V příkladu jsme vytvořili blok umocnit
a secist
, dál metodu vypocet
, které předáváme dva parametry (třídy Proc
), a ty v této metodě spustíme jejich jménem tak, jak jsme zvyklí.
Pokud se vám nyní ježí vlasy hrůzou, je to normální. Buď si zvyknete, nebo Ruby zavrhnete. ;-)
Vytvoření bloku z metody
Následující příklad je trochu záludný, a tak si ho dobře promyslete.
class Array
def polozky &neco
jeSude = true
self.each do |objekt|
if jeSude
neco.call objekt
end
jeSude = (not jeSude)
end
end
end
['jablko', 'hruška', 'švestka', 'pomeranč'].polozky do |ovoce|
puts 'Takže vy máte rádi ' + ovoce
end
zobrazí
Takže vy máte rádi jablko
Takže vy máte rádi švestka
Program vybere z pole položky umístěné na místě 0, 2, 4, … v poli a vypíše je. Volání neco.call
nás přenese do hlavního programu a provede vypsání textu na obrazovku. Všimněte si, že volaný text je vymezen direktivou do
a end
tak, jak jsme zvyklí. Takto vytvořený blok je nutno umístit na závěr všech parametrů metody a vždy mu předchází symbol &
.
Pokud není výše popsaná technika jasná, podívejte se na další příklad a k tomuto se vraťte později.
def zpracovani popis, &blok
zacatek = Time.now
blok.call
trvani = Time.now - zacatek
puts popis + ': ' + trvani.to_s + 's.'
end
zpracovani '25 000 sčítání' do
cislo = 1
25000.times do
cislo = cislo + cislo
end
puts 'Číslo má ' + cislo.to_s.length.to_s + ' míst.'
end
zpracovani '1 000 000 sčítání' do
cislo = 1
1000000.times do
cislo = cislo + 1
end
puts 'Číslo má ' + cislo.to_s.length.to_s + ' míst.'
end
zobrazí např.
Číslo má 7526 míst.
25 000 sčítání: 0.221906s.
1 000 000 sčítání: 1.183532s.
Délku druhého čísla si raději nevypisujte, jinak byste mohli ztratit některé iluze o počítačích… Matematicky řečeno - vzniklé číslo je strašně moc dlouhé.
Vlastní příklad si myslím nepotřebuje další vysvětlení, nejen že se dobře čte, dobře i funguje a tak by měl správný program vypadat.
Platí to i opačně, co je složité přečíst, to je složité i napsat. ;-)
Příklady 10
- Napište metodu, která vezme nějaký blok a zavolá ho každou hodinu, která dnes uplynula. Pro zjištění aktuální hodiny můžete použít funkci
Time.now.hour
.
A to je konec.
Seriál jsme pro vás připravili také v PDF pro tisk: Naučte se Ruby v PDF