Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Break out of a begin/end block early

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:

  • Assigning the variable within the begin block and returning
  • Putting the remaining portion of the begin block in an if statement
  • Performing the calculation before the begin block

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).

like image 358
Tom Prats Avatar asked Apr 17 '19 20:04

Tom Prats


1 Answers

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.

like image 139
mwp Avatar answered Oct 23 '22 08:10

mwp