为什么这个递归MyFunc [n_]:= MyFunc [n] = 2;结束?

时间:2013-01-22 09:21:11

标签: recursion wolfram-mathematica iteration

我不明白,为什么这个递归结束了:

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]]

导致“迭代”限制错误,而不是递归限制?

1 个答案:

答案 0 :(得分:1)

我的其他答案掩盖了一些重要的细节。这是第二个,我希望,更好的一个:

SetDelayed具有属性HoldAll,而Set具有属性HoldFirst。所以,你的定义

MyFunc[n_] := MyFunc[n] = 2;

存储时未评估任何部件。只有当你调用它时,例如 MyFunc[3]才会评估rhs,在本例中是一个涉及SetMyFunc[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]