Using 'return' in a Ruby block
Simply use next
in this context:
$ irbirb(main):001:0> def thing(*args, &block)irb(main):002:1> value = block.callirb(main):003:1> puts "value=#{value}"irb(main):004:1> end=> nilirb(main):005:0>irb(main):006:0* thing {irb(main):007:1* return 6 * 7irb(main):008:1> }LocalJumpError: unexpected return from (irb):7:in `block in irb_binding' from (irb):2:in `call' from (irb):2:in `thing' from (irb):6 from /home/mirko/.rvm/rubies/ruby-1.9.1-p378/bin/irb:15:in `<main>'irb(main):009:0> thing { break 6 * 7 }=> 42irb(main):011:0> thing { next 6 * 7 }value=42=> nil
return
always returns from method, but if you test this snippet in irb you don't have method, that's why you haveLocalJumpError
break
returns value from block and ends its call. If your block was called byyield
or.call
, thenbreak
breaks from this iterator toonext
returns value from block and ends its call. If your block was called byyield
or.call
, thennext
returns value to line whereyield
was called
You cannot do that in Ruby.
The return
keyword always returns from the method or lambda in the current context. In blocks, it will return from the method in which the closure was defined. It cannot be made to return from the calling method or lambda.
The Rubyspec demonstrates that this is indeed the correct behaviour for Ruby (admittedly not a real implementation, but aims full compatibility with C Ruby):
describe "The return keyword" do# ...describe "within a block" do# ...it "causes the method that lexically encloses the block to return" do# ...it "returns from the lexically enclosing method even in case of chained calls" do# ...
You are looking it from the wrong point of view.This is an issue of thing
, not the lambda.
def thing(*args, &block) block.call.tap do |value| puts "value=#{value}" endendthing { 6 * 7}