我不明白,为什么这个递归结束了:
In[27]:= MyFunc[n_] := MyFunc[n] = 2;
MyFunc[3]
Out[28]= 2
不应该是无穷无尽的
MyFunc[3]
MyFunc[3] = 2
(MyFunc[3] = 2) = 2
等等?
为什么会这样
MyFunc[n_] := MyFunc[n];
MyFunc[3]
During evaluation of In[31]:= $IterationLimit::itlim: Iteration limit of 4096 exceeded. >>
Out[33]= Hold[MyFunc[3]]
导致“迭代”限制错误,而不是递归限制?
答案 0 :(得分:1)
我的其他答案掩盖了一些重要的细节。这是第二个,我希望,更好的一个:
SetDelayed
具有属性HoldAll
,而Set
具有属性HoldFirst
。所以,你的定义
MyFunc[n_] := MyFunc[n] = 2;
存储时未评估任何部件。只有当你调用它时,例如 MyFunc[3]
才会评估rhs,在本例中是一个涉及Set
,MyFunc[3] = 2
的表达式。由于Set
具有属性HoldFirst
,因此该规则与其第一个参数(即 lhs)一起存储未经评估。在此阶段MyFunc[3]
,不会重新评估Set
表达式的lhs。但如果是这样,Mathematica会在不使用lhs MyFunc[3] = 2
规则的情况下找到规则MyFunc[3]
并将2
评估为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贪婪地评估函数调用的参数。
事实上,当试图理解这里发生的事情时,忘记任务和左右两侧可能会更容易,并记住一切都是表达式,例如,< / p>
MyFunc[n_] := MyFunc[n] = 2;
只是一种写作方式
SetDelayed[MyFunc[n_], MyFunc[n] = 2]