当使用Proc.new v。&符号时,为什么ruby中的break语句表现不同?

时间:2012-01-17 02:28:10

标签: ruby-on-rails ruby proc-object

块的break语句(根据The Ruby Programming Language)定义如下:

  

它导致块返回到它的迭代器,迭代器返回到调用它的方法。

因此,当运行以下代码时,会导致LocalJumpError。

def test
    puts "entering test method"
    proc = Proc.new { puts "entering proc"; break }
    proc.call # LocalJumpError: iterator has already returned
    puts "exiting test method"
end
test

以下代码不会抛出LocalJumpError。 &符号有什么特别之处? &符号是否隐含使用Proc.new?

def iterator(&proc)
    puts "entering iterator"
    proc.call # invoke the proc
    puts "exiting iterator" # Never executed if the proc breaks
end

def test
    iterator { puts "entering proc"; break }
end
test

换句话说,我读了&符号作为进入Proc.new电话的手段。此时行为应该与第一个代码段相同。

def iterator (p = Proc.new { puts "entering proc"; break})
...
end

免责声明 :我是新手学习语言(ruby 1.9.2),因此会非常感谢参考资料和详细的概要。

3 个答案:

答案 0 :(得分:7)

break使块块的调用者返回。在以下代码中:

proc = Proc.new { break }

转换为Proc对象的块的“调用者”是Proc.new。 break应该使块的调用者返回,但Proc.new已经返回。

在此代码中:

def iterator(&b); b.call; end
iterator { break }

该区块的来电者为iterator,因此会iterator返回。

答案 1 :(得分:3)

这是answer

Ampersand用于将proc转换为块,将块转换为proc。

我更改了示例,以便与您的案例相关:

def run_my_code(&my_code)
 puts 'before proc'
 my_code.call
 puts 'after proc'
end
run_my_code { puts "passing a block, accepting a proc"; break}
=> before proc
   passing a block, accepting a proc

正如你所看到的那样,它没有达到''proc'之后

def run_my_code
 yield
end
my_proc = Proc.new  { puts "passing a proc instead of block"; break}
run_my_code &my_proc
=> passing a proc instead of block
   LocalJumpError: break from proc-closure
   from (pry):75:in `block in <main>'

在你的第二个例子中,你有一个结果中的proc,proc从iterator开始并返回test函数。

def iterator(&proc)
  puts 'entering iterator'
  proc.call
  puts 'exiting iterator'
end

def test
  puts 'before test'
  iterator { puts 'entering proc'; break }
  puts 'after test'
end

=>before test
entering iterator
entering proc
after test

答案 2 :(得分:0)

它与块,触发器和lambdas之间的区别 - 以及它们各自的范围有关。

我在2009年写了一篇关于它的文章,你可能觉得它很有用:http://www.leonardoborges.com/writings/2009/07/22/procs-lambdas-blocks-whats-the-difference/

希望这有帮助。