我的另一个回答掩盖了一些重要的细节。这是第二个,我希望更好的一个:
SetDelayed有属性HoldAll,Set有属性HoldFirst。所以,你的定义
MyFunc[n_] := MyFunc[n] = 2;
存储时不评估任何部分。仅当您调用它时,例如 MyFunc[3]rhs 才被评估,在这种情况下为涉及Set,的表达式MyFunc[3] = 2。由于Set具有属性HoldFirst,因此该规则与其第一个参数(即lhs)一起存储,但未计算。在这个阶段,不重新评估表达式MyFunc[3]的 lhs 。Set但如果是这样,Mathematica 将找到规则MyFunc[3] = 2并计算结果MyFunc[3],2而不使用 lhs 规则MyFunc[n_]。
你的第二个定义,即
MyFunc[n_] := MyFunc[n];
也存储未评估。但是,当您调用函数时,例如 myFunc[3]rhs 会被评估。rhs 评估为,MyFunc[3]或者,如果你愿意,另一个调用MyFunc. 在MyFunc[3]Mathematica 的评估过程中找到存储的重写规则MyFunc[n_] := MyFunc[n]并应用它。反复。请注意,Mathematica 将此视为迭代而不是递归。
我并不完全清楚评估表达式的 lhs 可能实际上意味着什么。当然,像这样的调用MyFunc[3+4]实际上会导致MyFunc[7]被评估,因为 Mathematica 贪婪地评估函数调用的参数。
事实上,当试图理解这里发生的事情时,可能更容易忘记赋值和左右两边,并记住一切都是表达式,例如,
MyFunc[n_] := MyFunc[n] = 2;
只是一种写作方式
SetDelayed[MyFunc[n_], MyFunc[n] = 2]