Zdravím do programátorského koutku, přidám se něco z Ruby. Je to problém, zda je možné nějak ohnout bloky a yield naruby , případě jak dostat blok do vnitřního bloku(proc).
Mám takový to příklad (důležité je, že proměnná generator je daná a že je to typ Proc nebo Lambda.)
generator = proc {a,b=0,1 ; while(true) do a,b=b,a+b ; yield ; break if b>120 ; end}
generator.call{|v|p v}
LocalJumpError: no block given (yield)
from (irb):3019:in `block in irb_binding'
from (irb):3018:in `call'
from (irb):3018
Jak předám blok (například
{|res|puts res}, aby výsledek bylo vypsané 1\n2\n3,5,8...) tomuto Proc generator? Vím, že bloky jsou dělané na metody původně.
Samozřejmě to jde triviálně opravit(že předám blok jako argument, například pomocí &). Ale já právě chci zachovat původní formát
generator = proc {|&c|a,b=0,1 ; while(true) do a,b=b,a+b ; c.( b) ; break if b>120 ; end}
generator.call{|v|p v}
(v ruby pro Proc objekty jsou , prc.call a prc.yield , prc.() synonyma, a začíná v tom trochu bordel: .yield metody je něco jiného než yield klíčové slovo a prc() je chyba narozdíl od prc.() )
Pod čarou:
Inspirace vychází z konstrukce objektu Enumerator.new() (srozumitelnější pod pojmem Iterátor možná), který v konstruktoru přijímá
blok (s argumentem Enumerator::Yielder, přes který vrací hodnoty). Tělo bloku (Enumerator::Generator) je generující funkce. A aby Enumerátor fungoval, tělo funkce hodnoty vracet přes Enumerator::Yielder pomocí metody .<< (alias .yield, jde ale o třetí odlišnou yield konstrukci!)
it=Enumerator.new{|ýíldr| a=0 ; loop do a+=1 ; ýíldr << a ; end}
it.next , it.take(40), it.first ...
# Proč to nejde takto? Resp. jak to udělat
it=Enumerator.new{ a=0 ; loop do a+=1 ; yield a ; end}
# Ono i když generátor si deklaruji jako funkci (nikoli proc), tak i tak je s tím dost ohýbání
def gen() ; a=1; loop { a+=10 ; yield a ; sleep 0.1 } end
e=Enumerator.new {|yi|gen {|w|yi<<w} }.take(8)
def Enum_method(m) ; return Enumerator.new{|y|method(m).call{|v|y<<v}} end
Enum_method(:gen).take(4)
Zkoušeno: