尽早突破起点/终点

时间:2019-04-17 20:43:35

标签: ruby memoization

我想要一种退出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块中分配变量并返回
  • 将开始块的其余部分放在if语句中
  • 在开始块之前执行计算

关于突破限制似乎有很多相关问题,但我找不到一个能回答这个特定版本的问题(也许是因为不可能)。

1 个答案:

答案 0 :(得分:8)

如果您将所有逻辑放入自己的方法中,我想您会节省很多麻烦:

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和其他语言中相当普遍的设计模式。

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

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

但是您当然不会对自己或此代码的任何未来维护者有所帮助。