herophuong
herophuong

Reputation: 364

Ruby one time assignment on instance variable

I usually use "one time assignment" (don't really know how to call this anw) in ruby like this:

class FooBar
    def foo
       @foo ||= begin
           # Costly operation putting here
       end 
    end
end

This will allow the variable @foo to be computed only once, then being used directly in subsequent calls to method foo. My question are:

  1. Is using begin/end block in this case good or not, as the documentation states that it is used for encapsulating exceptions, doesn't mention any other uses.
  2. Can I use other block types (Proc, Lambda, do/end) with this syntax? If yes then how?

Upvotes: 0

Views: 163

Answers (2)

Windor C
Windor C

Reputation: 1120

  1. I haven't seen any usage of begin/end in the memorization, but I think that's fine.

  2. Of course, you can use lambda like this @foo ||= lambda { "foo" }.call, just remember that the one time assignment(||=) only evaluate the proc when @foo is evaluated to false. It's equivalent to the following:

    if @foo
      @foo
    else
      @foo = lambda { "foo" }.call
    end
    

Upvotes: 2

Nick Veys
Nick Veys

Reputation: 23939

I typically do it something like this:

class MyClass

  def foo
    @foo ||= build_foo
  end

  private

  def build_foo
    puts "I'm expensive"
    5
  end

end

I don't see why you'd need to make it any more complicated. To my eyes having a method named something like build_XXX or process_XXX clearly explains it's doing something more involved, and having the memoization take place in the publicly-accessible method makes it clear you are avoiding doing that more than once if needed.

Upvotes: 1

Related Questions