尽早突破起点/终点

Tom*_*ats 2 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
Run Code Online (Sandbox Code Playgroud)

我希望发生什么

> foo
running
=> leaving early
> foo
=> leaving early
Run Code Online (Sandbox Code Playgroud)

实际发生了什么

> foo
running
=> leaving early
> foo
running
=> leaving early
Run Code Online (Sandbox Code Playgroud)

该代码不起作用,因为return没有设置就退出了整个方法@foo。使用breaknext仅循环工作。开始中是否有任何事情可以阻止我的思维方式?

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

  • 在begin块内分配变量并返回
  • 将begin块的其余部分放在if语句中
  • 在开始块之前执行计算

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

mwp*_*mwp 8

I think you're going to save yourself a whole heck of a lot of strife if you just put all that logic into its own method:

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
Run Code Online (Sandbox Code Playgroud)

This decouples the computation from the memoization, making it easier to test and reason about, and it's a fairly common design pattern in Ruby and other languages.

Of course, there are ways of doing what you're asking. The most obvious solution being an immediately-invoked anonymous 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
Run Code Online (Sandbox Code Playgroud)

But you certainly wouldn't be doing yourself or any future maintainers of this code any favors.

  • 这是一个很好的建议,但它没有回答这个问题:“begin 中是否有任何东西阻碍了我的思考方式?”。 (2认同)