是否可以手动获取`yield`值而不是循环?

时间:2015-10-10 12:19:11

标签: crystal-lang

从文档中获取此示例,我们可以发送一个从函数中接收yield值的块。

def twice
  yield 1
  yield 2
end

twice do |i|
  puts i
end

我想知道的是,如果我们可以手动调用该函数,以便第一个调用给出1,那么我们会执行其他操作,然后下一个调用会给2

我试过(只是猜测)各种事情,比如puts twice(),但无济于事。有什么方法可以做到吗?

1 个答案:

答案 0 :(得分:4)

您可以使用spawn和channels。这是你能得到的最接近的地方:

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

你可以构建一个抽象,也许用宏:

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

可能使用包装器结构,因此它看起来像迭代器(http://crystal-lang.org/api/Iterator.html)。但请注意,这有点慢,至少比使用迭代器或常规非捕获块调用慢得多。