# Functions that remember their values

Can someone explain what is going on with the following ...

func[y_] := func[y] = (Print["Hello world !!!"];)

func[1]


Hello world !!!

func[2]


Hello world !!!

func[1] (*nothing printed*)

func[2] (*nothing printed*)


As I understand it () are used so the function remembers its values, but as you see when I repeat func[1], nothing.

If I take out the y in f[y], it prints. If I define the function as f[y_] := (...) (without f[y] = ), it prints.

I'm sure there is a simple explanation, any help is appreciated.

• There is one tiny syntactic subtlety in your code: (expr;) will return Null regardless of what expr evaluates to. – amr Jan 31 '13 at 2:49

The reason can be learned by inputting the following:

?func


This outputs the values currently assigned to your function func:

Globalfunc

func[1]=Null

func[2]=Null

func[y_]:=func[y]=Print[Hello world !!!]


When a function is evaluated that only prints, it assigns it a value of Null which is remembered by the memoization. The documentation covers this under "Properties & Relations".

• Of course, that makes complete sense. Thanks. – Alan Renton Jan 31 '13 at 1:04
• Glad I could help. – kale Jan 31 '13 at 1:52
• That isn't the only reason. The statement (Print[...];) is interpreted as CompoundExpression[Print[...], Null], and CompoundExpression returns the result of the last expression which is Null. So, the OP got hit with it twice, but only the CompoundExpression applies here. – rcollyer Jan 31 '13 at 2:53
• @rcollyer Yep, but the OP's conundrum exists in both cases with and without the semicolon, so I covered the most egregious issue. – kale Jan 31 '13 at 4:19

In some languages Print behaves like the identity function. But as noted, Print in Mathematica returns Null.

I want to make clear what is going on with the memoization idiom, for those who might be confused by it. I know I didn't really understand it at first.

func[y_] := func[y] = Print["Hello world !!!"];


This is clearer if it's written like this:

func[y_] := (
func[y] = Print["Hello world !!!"];
);


:= means evaluate each time.
= means only evaluate this once.

func[y_] means "match any singular pattern"
func[y] means "match only y's current value"

So the internal assignment is specifying an explicit value for a specific y. And the reason this idiom makes sense is because Mathematica essentially allows you to create multiple definitions for a single function. Examples:

myPrint[l_List] := Do[Print[x], {x, l}];
myPrint[else_] := Print[else];

f[1] = 1;
f[2] = 1;
f[n_] := f[n - 1] + f[n - 2];
`

So the memoization idiom is an automated version of this.