尽早突破开始/结束块

问题描述 投票:0回答:2

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

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
。使用
break
next
只能在循环中使用。开始内有什么工作会阻碍我的思考方式吗?

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

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

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

ruby memoization
2个回答
19
投票

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

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

但是您肯定不会为您自己或此代码的任何未来维护者带来任何好处。


0
投票

您可以使用

loop do ... end
结构代替
begin ... end

在这种情况下,您可以使用
break <value>
从块返回值。

def foo
  @foo ||= loop do
     puts "running"

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

     # Other calculations
     break "leaving at the end"
  end
end

这将为您带来预期的结果:

> foo
running
=> leaving early
> foo
=> leaving early
© www.soinside.com 2019 - 2024. All rights reserved.