我有以下Ruby代码:
# func1 generates a sequence of items derived from x
# func2 does something with the items generated by func1
def test(x, func1, func2)
func1.call(x) do | y |
func2.call(y)
end
end
func1 = lambda do | x |
for i in 1 .. 5
yield x * i
end
end
func2 = lambda do | y |
puts y
end
test(2, func1, func2) # Should print '2', '4', '6', '8', and '10'
当然,这不起作用。
test.rb:11: no block given (LocalJumpError)
from test.rb:10:in `each'
from test.rb:10
from test.rb:4:in `call'
from test.rb:4:in `test'
from test.rb:20
答案 0 :(得分:12)
Lambda不会像常规方法那样隐式接受块,因此func1
无法屈服。这样做:
func1 = lambda do |x, &blk|
for i in 1 .. 5
blk.call(x * i)
end
end
具体来说,我认为这是因为yield会将控制权发送回caller
的块,这不包括lambda调用。所以下面的代码就像你“期待”一样:
def foo
(lambda { |n| yield(n) }).call(5)
end
foo { |f| puts f } # prints 5
答案 1 :(得分:4)
仅限Ruby 1.9:
func1 = lambda do |x, &blk|
for i in 1..5
blk.call(x*i)
end
end
答案 2 :(得分:1)
def test(x, func1, func2)
func1.call(x) do | y |
func2.call(y)
end
end
#change func1 to a method
def func1 x
for i in 1 .. 5
yield x * i
end
end
#func2 may be either a method or a lambda
#I changed it for consistency, but you don't have to
def func2 y
puts y
end
test(2, method(:func1), method(:func2))
答案 3 :(得分:0)
基于Nikita Misharin在这里的答案:[https://stackoverflow.com/a/45571976/2165560],我喜欢这个:
def iterator(x)
for i in 1 .. 5
yield x * i
end
end
iteratorWrapper = -> (m,&block) { iterator(m) {|n| block.call n} }
iteratorWrapper.call(2) { |y| puts y }
它在这里回答了我的问题[In Ruby, can you use the lambda or or Proc call method to invoke an iterator?。
通过包装迭代器,它可以任意传递给其他方法并迭代它们的块。