In many cases, memoization helps for a given particular computation, and one can (or even has to) then remove the memoized values. For such cases, protection can nicely coexist with the technique which I call "self-blocking". I will illustrate this using the infamous Fibonacci numbers example:
fib = fib = 1;
fib[m_?Positive] := fib[m] = fib[m - 1] + fib[m - 2];
Protect @ fib;
Now, we can use, for example:
(* 573147844013817084101 *)
while e.g. the following assignment is not allowed:
fib = 1
During evaluation of In:= Set::write: Tag fib in fib is Protected.
(* 1 *)
The reason this works is that
Block removes all global properties of the blocked symbol, including the
Protected attribute. Note that this technique also guarantees that the memoized values are removed after the function finishes, since they only exist inside a dynamic environment created using
In more complex cases, some variations of this approach might work as well.
To address your question on how to keep the generated definitions, here is another method. First, define this handy macro, which allows us to avoid extra scoping constructs (intermediate variables):
withCodeAfter[before_, after_] := (after; before);
Now, here is the method (using the same example as before): before all your usual definitions, insert an extra definition:
call_fib /; MemberQ[Attributes[fib], Protected] :=
withCodeAfter[Unprotect[fib]; call, Protect[fib]]
fib = fib = 1;
fib[n_] := fib[n] = fib[n - 1] + fib[n - 2];
This extra definition allows the function, but only the function, to modify itself during its own execution. So, now:
(* 20365011074 *)
And you can check that the function remains
Protected, and the generated definitions are now in the global rule base.
This method is general, so all you have to do is to insert your own symbol in place of
fib, to construct a relevant extra definition for your problem / function. It is important that it is the very first one you give, so it should go before your "usual" definitions.