尽早突破 begin/end 区块

Break out of a begin/end block early

我想要一种方法来退出 begin/end 块,同时仍然分配其结果分配给的变量。

def foo
  @foo ||= begin
    puts "running"

    return "leaving early" if true # would be some sort of calculation

    # Other calculations
  end
end

我希望发生什么

> foo
running
=> leaving early
> foo
=> leaving early

实际发生了什么

> foo
running
=> leaving early
> foo
running
=> leaving early

代码不起作用,因为 return 没有设置 @foo 就退出了整个方法。使用 breaknext 只能在循环中使用。 begin 块中的任何东西都按照我的想法工作吗?

我目前可以做到但希望避免的方法:

好像有很多关于breaking out of blocks的相关问题,但是我找不到一个可以回答这个特定版本的问题(也许是因为这是不可能的)。

我认为,如果您将所有这些逻辑都放入其自己的方法中,您将会避免很多冲突:

def foo
  @foo ||= compute_foo
end

def compute_foo
  puts "running"

  return "leaving early" if true # would be some sort of calculation

  # Other calculations
end

这将计算与记忆分离,使其更易于测试和推理,并且它是 Ruby 和其他语言中相当常见的设计模式。

当然,有多种方法可以满足您的要求。最明显的解决方案是立即调用匿名过程:

def foo
  @foo ||= (proc do
    puts "running"

    next "leaving early" if true # would be some sort of calculation

    # Other calculations
  end)[] # or .call or .()
end

但是您肯定不会帮您自己或此代码的任何未来维护者任何忙。