2

I want to know why I cannot return from this block:

[1,2].each { |e| return e } # => LocalJumpError: unexpected return

while these work:

[1,2].each { |e| Proc.new {return e} } # => [1, 2]
[1,2].each { |e| lambda {return e} } # => [1, 2]

Hope someone can explain.

sawa
  • 165,429
  • 45
  • 277
  • 381
pangpang
  • 8,581
  • 11
  • 60
  • 96
  • Try out your code again but this time call the proc and the lambda (as the block also gets called). You'll see that the proc one will also raise. That's because blocks and procs are the same however lambdas act like methods. See http://www.reactive.io/tips/2008/12/21/understanding-ruby-blocks-procs-and-lambdas/ or SO answers like https://stackoverflow.com/questions/1435743/why-does-explicit-return-make-a-difference-in-a-proc – cremno Jun 04 '15 at 09:24
  • 1
    Also see http://stackoverflow.com/a/1402764/192702. It looks a little bit strange without an enumerator like `each`, but you can use the `next` keyword to exit any block. – Patrick Oscity Jun 04 '15 at 09:27

2 Answers2

2

You can use return inside a block in Ruby. It will return from the enclosing method. In this case, there is no enclosing method, that's why there is an error, it's not because return in a block is illegal

rick
  • 1,675
  • 3
  • 15
  • 28
0

Open a ruby console (using irb or rails console) in a terminal and type return 10. It should give you the following error:

2.6.9 :020 > return 10
Traceback (most recent call last):
        2: from (irb):20
        1: from (irb):20:in `rescue in irb_binding'
LocalJumpError (unexpected return)

This is cause there's no enclosing method. To use return you must be returning from something.

When you use return in a Proc it is essentially like calling return from the most upstream context.

So if you execute your example in the console

[1,2].each { |e| return e }

it essentially doing the same thing as typing

return 1
return 2

in the console.


Your other examples don't actually execute what's in the nested proc / lambda which is why there is no error.

But if you call the proc it will throw the same error

[1,2].each { |e| Proc.new { return e }.call } # => LocalJumpError (unexpected return)

The lambda returns in the local context so there's no error

[1,2].each { |e| lambda { return e }.call } # => [1, 2] 

This answer has some more examples on using return within a proc or lambda

CBK
  • 141
  • 1
  • 6