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

Recursion 为什么这个递归函数是MyFunc[n_]:=MyFunc[n]=2;结束?,recursion,wolfram-mathematica,iteration,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

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

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

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

我的另一个答案忽略了一些重要的细节。这是第二个,我希望是更好的:

SetDelayed
具有属性
HoldAll
,而
Set
具有属性
HoldFirst
。那么,你的定义是什么

MyFunc[n_] := MyFunc[n] = 2;
存储时未评估零件。只有在调用它时,例如
MyFunc[3]
才会对rhs求值,在本例中,rhs求值的表达式涉及
Set
MyFunc[3]=2
。由于
Set
具有属性
HoldFirst
,因此存储此规则时未计算其第一个参数(即lhs)。在此阶段,
MyFunc[3]
不会重新计算
集合
表达式的lhs。但如果是,Mathematica将找到规则
MyFunc[3]=2
,并将
MyFunc[3]
计算为
2
,而无需将该规则与lhs
MyFunc[n_]
一起使用

你的第二个定义,即

也存储为未评估。但是,当您调用函数时,例如
myFunc[3]
,将对rhs进行计算。rhs的计算结果为
MyFunc[3]
,或者,如果您愿意,可以再次调用
MyFunc
。在计算
MyFunc[3]
Mathematica的过程中,会找到存储的重写规则
MyFunc[n\u]:=MyFunc[n]
,并应用它。反复地请注意,Mathematica将此视为迭代而不是递归

我并不完全清楚计算表达式的lhs实际上意味着什么。当然,像
MyFunc[3+4]
这样的调用实际上会导致计算
MyFunc[7]
,因为Mathematica贪婪地计算函数调用的参数

事实上,当试图理解这里发生的事情时,可能更容易忘记赋值和左右两边,记住一切都是一个表达式,例如

MyFunc[n_] := MyFunc[n] = 2;
这只是一种写作方式

SetDelayed[MyFunc[n_], MyFunc[n] = 2]

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

SetDelayed
具有属性
HoldAll
,而
Set
具有属性
HoldFirst
。那么,你的定义是什么

MyFunc[n_] := MyFunc[n] = 2;
存储时未评估零件。只有在调用它时,例如
MyFunc[3]
才会对rhs求值,在本例中,rhs求值的表达式涉及
Set
MyFunc[3]=2
。由于
Set
具有属性
HoldFirst
,因此存储此规则时未计算其第一个参数(即lhs)。在此阶段,
MyFunc[3]
不会重新计算
集合
表达式的lhs。但如果是,Mathematica将找到规则
MyFunc[3]=2
,并将
MyFunc[3]
计算为
2
,而无需将该规则与lhs
MyFunc[n_]
一起使用

你的第二个定义,即

也存储为未评估。但是,当您调用函数时,例如
myFunc[3]
,将对rhs进行计算。rhs的计算结果为
MyFunc[3]
,或者,如果您愿意,可以再次调用
MyFunc
。在计算
MyFunc[3]
Mathematica的过程中,会找到存储的重写规则
MyFunc[n\u]:=MyFunc[n]
,并应用它。反复地请注意,Mathematica将此视为迭代而不是递归

我并不完全清楚计算表达式的lhs实际上意味着什么。当然,像
MyFunc[3+4]
这样的调用实际上会导致计算
MyFunc[7]
,因为Mathematica贪婪地计算函数调用的参数

事实上,当试图理解这里发生的事情时,可能更容易忘记赋值和左右两边,记住一切都是一个表达式,例如

MyFunc[n_] := MyFunc[n] = 2;
这只是一种写作方式

SetDelayed[MyFunc[n_], MyFunc[n] = 2]