Taking this example from the docs, we can send a block that receives the yield
values from the function.
def twice
yield 1
yield 2
end
twice do |i|
puts i
end
What I'm wondering is if we can manually call on the function so that the first call gives 1
then we do other stuff, and then the next call gives 2
.
I tried (just guessing) various things, like puts twice()
but to no avail. Is there any way this can be done?
You can use spawn and channels. This is the closest you can get:
def foo
yield 1
yield 2
end
chan = Channel(typeof(foo { |x| x })).new
spawn do
foo do |x|
chan.send x
end
chan.close
end
p chan.receive?
p chan.receive?
p chan.receive?
http://play.crystal-lang.org/#/r/ijd
You could build an abstraction over that, maybe with macros:
def foo
yield 1
yield 2
end
macro enumerator(call)
%chan = Channel(typeof({{call}} { |x| x })).new
spawn do
{{call}} do |x|
%chan.send x
end
%chan.close
end
%chan
end
values = enumerator(foo)
p values.receive?
p values.receive?
p values.receive?
http://play.crystal-lang.org/#/r/ije
And probably using a wrapper struct so it looks like an Iterator ( http://crystal-lang.org/api/Iterator.html ). But note that this is kind of slow, at least much slower than using an iterator or a regular non-captured block call.