If I understand you correctly that's a tighter implementation you're talking about (and what I was originally talking about in this proposal), i.e. memoizing a method with an argument list equal to  (an empty list). The first time this method gets called with the argument list equal to  it calculates the result, caches it in a hash table like so: cache[] = result and returns the result. Every other time it's called it simply returns cache[].
Storing the results in a hash table allows to also cache all the other executions of this method, for instance, calling it with an argument list [1231, "asdfa"] will at first execution create another record in the cache like so: cache[[1231, "asdfa"]] = result and return it all the other times the method gets called with arguments [1231, "asdfa"].
This technique has a very wide application range, not just math calculations - basically, any side-effectless method. For instance parsing the same file, of which you know that it didn't change, making a remote request which you know to bring you the same result - basically any operation you know to take longer than a hash-table search.
This technique will require additional RAM, but then again it will still be managed garbage collector.
On the question about restricting it to immutables only - i think it would be an overcomplication. The user of the feature should know what he's doing, otherwise he doesn't have a reason to do it. Any kind of restriction would be an overcomplication resulting in excessive calculations actually since since it's a dynamic language, and again since it's a dynamic language it won't make sense anyway. This feature really is a basic stuff.