2010-12-01 48 views
1

我的功能bar得到一個塊,我想運行這個塊而不允許它到return。我如何通過修改下面的bar來完成此操作,並保持其他所有操作(包括foo)完好無損?如何在Ruby中返回LocalJumpError?

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

我很好奇,你爲什麼會想要做這樣的事情? – Chubas 2010-12-01 15:47:39

+0

我想在Ruby 1.8中模擬`Fiber`,`Fiber.new {...}`不支持`return` - 所以仿真也不能支持它。順便說一下,我已經放棄了仿真(都是用`callcc`和`Thread`),因爲我可以寫它,所以它不會泄漏內存。 – pts 2010-12-06 09:17:17

回答

0

基於在其他的答案的建議,我已成功地解決了這個問題:

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 
1

那麼,當您嘗試,並通過一個塊用 returnProc(而不是一個 lambda)獲得 LocalJumpError

你可以逃脫不改變foo,除了它是如何調用,如果你這樣做

def bar() 
    Proc.new 
end 

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

foo[] 

,給出了一個LocalJumpError

無論如何, this article可能會有所幫助。

編輯:A return在proc中將從外部方法返回,而不是從塊中的匿名方法返回。你也許可以設置一個標誌,你可以在bar檢查,看它是否過早返回:

bar_finished = false 

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

然後,如果return是傳遞給bar塊,bar_finished仍將是假的。不知道是否添加像這樣的非局部變量是一個選項,但如果是這樣,您可以跟蹤塊返回,並拋出任何異常,如果它發生。

+0

雖然你的回答很有洞察力,但它並不回答我的問題。在我的問題中,有一個要求是不改變`bar`外的其他任何東西。你已經發布了一個將`foo`改爲`foo []`的答案。你有隻改變`bar`的解決方案嗎? – pts 2010-12-01 16:20:54

1

如果您想在yield之後完成某些「清理」代碼,那麼您可能需要使用begin,然後使用ensure