从matz ruby切换到jruby时出现奇怪的“return”行为

从matz ruby切换到jruby时出现奇怪的“return”行为,ruby,jruby,behavior,incompatibility,Ruby,Jruby,Behavior,Incompatibility,为什么这段代码: 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(2014-05-08)[

为什么这段代码:

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(2014-05-08)[x64-mingw32]打印
2
但是jruby 1.7.15(1.9.3p392)2014-09-03中的
1
在Java HotSpot(TM)64位服务器虚拟机上的82b5cc3 1.7.0_67-b01+jit[Windows 8-amd64]

我想了解这个问题


UPD:是否应该在某处报告?

lambda中的“return”应该从lambda返回,而不是从方法返回。 在这种棘手的情况下,jruby似乎不尊重内部lambda,而是返回到第一个lambda调用

起初我认为这可能是由lambda中的lambda调用引起的,但现在我认为这是一个与块转换相关的问题,将示例简化为:

Module.new do
  test = lambda do
    return
  end
  module_exec &test
  puts 'after'
end
这里只有mri打印“之后”,而jruby什么也不打印

…但如果我们不进行lambda到块的转换(测试(&T):


mri和jruby打印'after'…

我总是觉得块内的
返回是未定义的行为。你能改用
next

例如,Rubinius也有这个问题,但要明确得多:

[1].map(&lambda { |n| return -1 })
LocalJumpError: unexpected return
当然,使用
next
会产生预期的结果:

rbx-head :003 > [1].map(&lambda { |n| next -1 })
 => [-1] 
这个故事的寓意是
return
是为方法定义的,而proc和lambda不是方法<代码>下一步
中断
是要停止块调用时使用的关键字

我在官方Ruby规范中找不到任何关于
return
行为的文档,但是
rubyspec
确实有验证
return
导致调用方法返回的测试


您确定没有将它们相互替换吗?我的jruby通过所有调用返回——这就是我发现问题的原因。原始代码正在遍历一棵树,必须返回一个长向量,但jruby抛出了nil,在我的程序中引发了进一步的异常。我记得,当我在原始代码中尝试使用
{test[]}
而不是
&test
时,它有另一个作用域,没有看到模块方法,等等。,所以这个替换不是等价的。是的,我正试图找出原因。试试这个:def测试;[1] .map(&lambda{n}返回-1});endI刚刚将此添加到jruby问题跟踪器:块不应处理返回,只应处理周围的方法。然而,lambda应该具有方法语义。转换为块时,lambda保留其lambda状态,因此。。。。这是我找到的所有参考资料,我刚刚测试过。在MRI中,当调用
到\u proc
时,lambda保持其lambda属性。另一方面,在rbx中,lambda属性丢失(例如,丢失的方法不会引发错误)。
rbx-head :003 > [1].map(&lambda { |n| next -1 })
 => [-1]