You can see the final product of this article here
as of Ruby 2.1.0, method
definitions grew a return value. Method Definitions now return the
method name as a symbol. This allow for some interesting things like
private method declaration.
Note: Inline private method declarations only works for instance methods. Because
defis returning a symbol representing the method name, it does not know the owning object.
so this got me thinking, what else could you use in front of a method definition?
Note: Throughout this post I used
memoizeinterchangeably. In reality,
memoizationis a special case of
caching. In this article, all caching is memoization caching.
I see the
@expensive_value ||= expensive_computation pattern far too
much. I wonder if we can do that automatically by using the return
I do like how
cache def looks and after exploring this problem,
turns out the implementation is not that ridiculous either.
NOTE: I dislike the double
instance_eval, but I couldn’t find a better way of sending arguments along to the
To get this new behavior just
in your class and enjoy method caching.
Lets walk through the code
- We alias the method we have just defined to the
recompute_prefixed version of itself.
- Name the variable we will be storing the expensive computation in.
- Then, redefine the method we original method to first check the instance variable, then do the computation if it isn’t already saved.
an added advantage of this approach is that we have access to the
recompute_method method elsewhere in our code. This lets us bust the
cache if we want. There are tons of uses for having a return value
from function definition. you can store source annotations, or use it
to register the method with a callback.
One thing I wonder after this exploration is have we actually made the code better? I am honestly unsure. We pulled a common idiom into a single word that actually provides additional functionality that was not there before. I suppose it is up to the user if it is worth having this extra layer of magic to provide a different way of caching the return value of a method.