我的另一个回答掩盖了一些重要的细节。这是第二个,我希望更好的一个:
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]