2015-10-10 30 views
2

以文档中的示例为例,我们可以发送一个从该函数接收yield值的块。是否可以手动获取yield值而不是循环?

def twice 
    yield 1 
    yield 2 
end 

twice do |i| 
    puts i 
end 

什么我不知道,如果我们可以手动在功能调用,这样第一个电话给1然后我们做其他的东西,然后下一个电话给2

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

回答

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)。但请注意,这样做比较慢,至少比使用迭代器或常规未捕获块调用慢得多。

+0

感谢那个有趣的解决方案,虽然它不适合我的情况。认为可能有一些功能像ECMAScript6具有其生成器功能,但我可以解决它。再次感谢! –

相关问题