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

时间:2022-06-05 01:45:05

The break statement for blocks (as per The Ruby Programming Language) is defined as follows:

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

it causes the block to return to its iterator and the iterator to return to the method that invoked it.

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

Therefore when the following code is run, it results in a LocalJumpError.

因此,当运行以下代码时,它会导致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

While the following code does not throw a LocalJumpError. What is special about the ampersand sign? Doesn't the ampersand sign implicitly use Proc.new?

虽然以下代码不会抛出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

In other words, I read the ampersand sign as a means of in-lining the Proc.new call. At which point the behavior should be just the same as the first code snippet.

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

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

Disclaimer: I am newb learning the language (ruby 1.9.2), and therefore will appreciate references and a detailed synopsis.

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

3 个解决方案

#1


7  

break makes the block and the caller of the block return. In the following code:

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

proc = Proc.new { break }

The "caller" of the block which is converted to a Proc object is Proc.new. break is supposed to make the caller of the block return, but Proc.new has already returned.

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

In this code:

在这段代码中:

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

The caller of the block is iterator, so it makes iterator return.

块的调用者是迭代器,因此它使迭代器返回。

#2


3  

Here's the answer.

这是答案。

Ampersand is used to convert a proc to a block and a block to a proc.

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

I changed the example so as to relate to your case:

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

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

As you can see it didn't reach the 'after 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>'

In your second example you have a proc in result, the proc breaks from iterator and returns to test function.

在你的第二个例子中,你有一个结果中的proc,proc从迭代器中断并返回测试函数。

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

#3


0  

It has to do with the difference between blocks, procs and lambdas - and their respective scopes.

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

I wrote a post about it back in 2009 that you might find useful: http://www.leonardoborges.com/writings/2009/07/22/procs-lambdas-blocks-whats-the-difference/

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

Hope this helps.

希望这可以帮助。

#1


7  

break makes the block and the caller of the block return. In the following code:

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

proc = Proc.new { break }

The "caller" of the block which is converted to a Proc object is Proc.new. break is supposed to make the caller of the block return, but Proc.new has already returned.

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

In this code:

在这段代码中:

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

The caller of the block is iterator, so it makes iterator return.

块的调用者是迭代器,因此它使迭代器返回。

#2


3  

Here's the answer.

这是答案。

Ampersand is used to convert a proc to a block and a block to a proc.

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

I changed the example so as to relate to your case:

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

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

As you can see it didn't reach the 'after 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>'

In your second example you have a proc in result, the proc breaks from iterator and returns to test function.

在你的第二个例子中,你有一个结果中的proc,proc从迭代器中断并返回测试函数。

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

#3


0  

It has to do with the difference between blocks, procs and lambdas - and their respective scopes.

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

I wrote a post about it back in 2009 that you might find useful: http://www.leonardoborges.com/writings/2009/07/22/procs-lambdas-blocks-whats-the-difference/

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

Hope this helps.

希望这可以帮助。