Adarsh Pandit

Software Developer

Use an Underscore When Memoizing in Ruby

By Adarsh Pandit in writing

TLDR;

Do this:

def expensive_method
  @_expensive_method ||= #something
end

Not this:

def expensive_method
  @expensive_method ||= #something
end

Memo_pad

Memoization Basics

The act of “memoizing” a method means to locally cache the result of an expensive operation on the first method invocation and reusing it thereafter.

It is functionally equivalent to:

def expensive_method
  @expensive_method = @expensive_method || this_expensive_operation
end

Naming

By convention, you typically see developers name the instance variable after the method. Likely, this is because manual instance variable accessors used to look like this:

def expensive_method
  @expensive_method
end

Nowadays, we usually write attr_reader :expensive_method.

Unused Variables

Keen readers will note we are actually instantiating an instance variable here. That means we can access it from other instance methods. Not a huge deal, but it’s intended for internal use when memoizing.

Enter the underscore.

It is convention in many languages including Ruby to prepend an unused variable name with an underscore.

The underscore serves as a signal to other developers saying “Hey! Don’t use this!”.

We should do the same when memoizing:

def expensive_method
  @_expensive_method ||= #something
end

This is, of course, a style preference with no functional impact. It’s also just my opinion, man.

Instance Variables in Controllers

Also, as my friend Gabe pointed out to me, it’s even more important to use an underscore when memoizing in Rails controllers:

“Since all controller ivars are available in the view, it’s often helpful to mark ivars that should only be used in the controller with a leading underscore. That also allows things like this, where @users is exposed to the view and @_users is just used for memoization:”

def index
  @posts = posts.where(user: users.where(has_post: true))
  @users = users.where(confirmed: true)
end

private

def users
  @_users ||= User.all
end

It’s good to have smart friends.

Further Reading

692dad2af6224bf856e94a96049292c4
Written by Adarsh Pandit

Read more posts by Adarsh, and follow Adarsh on Twitter.