开发者

How to force a LocalJumpError on return in Ruby?

My function bar gets a block, and I'd like to run this block without allowing it to return. How do I do that by modifying only bar below, and keeping everyth开发者_高级运维ing else, including foo, intact?

def bar()
  yield
end
def foo()
  bar do
    p "it"
    return  # This works. But I'd like to get LocalJumpError.
  end
end
foo


Well, you get a LocalJumpError when you try and pass a block with a return to a Proc (as opposed to a lambda).

You can get away with not changing foo except for how it's called, if you do something like

def bar()
  Proc.new
end

def foo()
  bar do
    p "it"
    return
  end
end

foo[]

That gives a LocalJumpError.

Anyway, this article might help.

Edit: A return in a proc will return from the outer method, not from the anonymous method in the block. You might be able to set a flag that you can check in bar to see if it returned prematurely:

bar_finished = false

def bar(&block)
  proc = Proc.new &block
  l.call
  bar_finished = true
end

Then, if a return is in the block passed to bar, bar_finished will still be false. Not sure if adding a non-local variable like this is an option, but if so, you could track returns from the block and throw whatever exception you want if it happens.


If there's some "cleaning up" code you want done after yield, then you may want to use begin and then ensure.


Based on suggestions in other answers, I have managed to solve the problem:

def bar()
  has_returned = true
  begin
    x = yield
    has_returned = false
    x
  rescue
    has_returned = false
    raise
  ensure
    raise LocalJumpError if has_returned
  end
end
def foo()
  bar do
    p "it"
    return  # This makes bar raise a LocalJumpError.
  end
end
foo
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜