为什么这个片段:
def dump_dump
get_dump = lambda do
return 1 if $n
$n = true
module_exec &get_dump
2
end
p get_dump[]
end
Module.new do
module_exec &method(:dump_dump)
end
在ruby 2.0.0p481中打印2
(2014-05-08)[x64-mingw32]
但在Java HotSpot(TM)64位服务器VM上的jruby 1.7.15(1.9.3p392)2014-09-03 82b5cc3中1
1.7.0_67-b01 + jit [Windows 8-amd64]?
我想了解这个问题。
UPD:应该在某处报道吗?答案 0 :(得分:2)
我总是认为块内的return
是未定义的行为。您可以使用next
吗?
例如,Rubinius也有这个问题,但更为明确:
[1].map(&lambda { |n| return -1 })
LocalJumpError: unexpected return
当然,使用next
会产生预期的结果:
rbx-head :003 > [1].map(&lambda { |n| next -1 })
=> [-1]
故事的寓意是return
是为方法定义的,而Proc和lambdas不是方法。如果您希望停止阻止调用,则next
和break
是要使用的关键字。
我无法从官方Ruby规范中找到有关return
行为的任何文档,但rubyspec
确实有验证return
导致调用方法的测试回来。
https://github.com/rubyspec/rubyspec/blob/master/language/return_spec.rb#L184
答案 1 :(得分:0)
lambda中的'return'应该从lambda返回而不是从方法返回。 在这个棘手的情况下,看起来jruby不尊重内部lambda,而是一直返回到第一个lambda调用。
起初我以为它可能是由lambda中的lambda调用引起的,但现在我认为这是一个与块转换相关的问题,在将示例简化为此之后:
Module.new do
test = lambda do
return
end
module_exec &test
puts 'after'
end
这里只有mri打印'after',而jruby打印没有。
...但如果我们不做lambda来阻止转换(& test):
Module.new do
test = lambda do
return
end
module_exec { test[] }
puts 'after'
end
mri和jruby都打印'之后'......