Also, lack of encapsulation. You shouldn’t be able to reach into the innards of an object and mutate its state without at least telling it!
Ha! I love Ruby to bits but try telling it about orderly encapsulation and it’s in one ear and out the other.
[Comment removed by author]
My reaction is ‘then you’re doing it wrong’ :)
Memoization is a kind of mutability, but it does not affect reasoning about code function, though it makes reasoning about code timing harder (just like mutability makes reasoning about code function harder).
I was a little disappointed: I was thinking this would be a discussion of how, due to locality effects, memoization can actually make a function slower, or something deep like that.
Mutability is the root cause. You can avoid this problem by reducing mutability one way or the other:
Implemented correctly, memoization does not result in mutability to the operation of the function. It does some funny things to, effectively, how the function is implemented. Usually we shunt out a full computation for a hash based look up.
That seems completely besides the point. The key phrase is in “implemented correctly”.
This article is not called “memoization considered harmful”. Essentially it’s criticising premature optimization.
I upvoted the article just so people could see this comment. It really helps illuminate how people project their issues onto the layer they’re working with instead of looking into root causes.
As much as your programming language makes immutability a virtue, your database will stay mutable - and that’s where memoization is often used.
I think people that get into Ruby via Rails are naturally prone to over-caching in the exact way that is outlined here. In Rails, it’s almost 100% safe to use this type of caching in a controller method because each request makes a new instance of the controller processing it. It’s also incredibly useful to cache results of I/O operations (think isloggedin? or current_user type results) to improve code quality in the meat of the methods. But back to my point, when you step outside of Rails into the vanilla Ruby world, it’s all too easy to use that in places where it doesn’t apply.
Another angle to consider is that naive memoization is not threadsafe. I have had this come up in some interesting places such as caching within metaprogramming. These sorts of issues can be quite difficult to isolate.