I want a way to exit a begin/end block while still assigning the variable that its result is assigned to.
def foo
@foo ||= begin
puts "running"
return "leaving early" if true # would be some sort of calculation
# Other calculations
end
end
What I hope to happen
> foo
running
=> leaving early
> foo
=> leaving early
What actually happens
> foo
running
=> leaving early
> foo
running
=> leaving early
The code doesn't work because return
exits the entire method without setting @foo
. Using break
or next
only work in loops. Does anything work within a begin block the way I'm thinking?
Current ways I can do it but was hoping to avoid:
There seem to be a lot of related questions about breaking out of blocks but I couldn't find one that answers this specific version (maybe because it's not possible).
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
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
But you certainly wouldn't be doing yourself or any future maintainers of this code any favors.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With