Memoization in Ruby
This tutorial will help you understanding Memoization pattern in Ruby. Memoization is different from Lazy Initialization. Rails had Memoize to support memoization pattern which will be discussed as well.
What is Memoization?
Memoization can be used to initialize a variable and store it with the result of some computation that is expected to give same result if computed again. Then, the variable is used to return result instead of doing the computation again when needed again.
E.g.
def user_score
@user_score ||= # some complex calculation for user score
end
The method user_score
calculates score based on some complex calculation
and
stores it in the instance variable @user_score
.
When code/flow needs value of user_score
again then
if value @user_score
is set then it is returned instead of computing again.
Above statement can also be written as,
@user_score = @user_score || # some complex calculation for user score
This is simplified version.
When to use Memoization
-
When you have complex calculation that is supposed to give same result on multiple calls
-
When you have database query with same parameters for a instance
e.g.
def user_score
@user_score ||= User.where(name: 'Sam').first.try(:name)
end
If you need user Sam’s score then you can calculate and store it. When you need again then you can just return it from the instance variable.
- When you have a method that is giving same result over multiple calls but you need to call it multiple times
What about nil, false?
Memoization technique discussed above does not work with nil, false values. Let us see why.
@variable ||= false # suppose calculation value is false
which simplifies as
@variable = @variable || false
As @variable had false value it will again go and evaluate for the OR part of condition which will come out false again.
Same will happen in case of nil as well.
Thus, over multiple calls Memoization will not work if value comes out to be nil, or false.
Solution to nil, false scenario for Memoization
def variable
@variable = false unless instance_variable_defined? :@variable
@variable
end
This will not perform calculation which returns result false/nil if the @variable value is already defined. Thus, this solution holds the memoization pattern.
Confused with Lazy Initialization?
What is Lazy initialization?
Lazy initialization is delaying intialization of the object/entity until the need of it for first time.
class User
def initialize
@user_score = # same complex caluclation for user score
end
end
This is example of Not Using Lazy Initialization.
@user_score
is calculation at the construction time.
class User
def initialize
end
def user_score
@user_score ||= # same complex caluclation for user score
end
end
This is the example of lazy intialization in above context. This is use of Memoization in combination with Lazy intialization.
Does Rails support Memoization?
Rails had support for Memoize through ActiveSupport::Memoizable. Memoizable is deprecated from Rails.
We will not go in deep understanding Memoize from Rails as it has been deprecated.
Check this commit as to why Memoizable support has been deprecated.
References
Memoization | Lazy Initialization
Feel free to comment if you have any doubts/suggestions.
Subscribe to Ruby in Rails
Get the latest posts delivered right to your inbox
![Buy me a coffee](https://cdn.buymeacoffee.com/buttons/default-blue.png)