这个讨论出现在previous question中,我很想知道两者之间的区别。举例说明会很好。
答案 0 :(得分:16)
以下是Leonid Shifrin的书Mathematica programming: an advanced introduction
中的一个例子ClearAll[a, b]
a = RandomInteger[{1, 10}];
b := RandomInteger[{1, 10}]
Table[a, {5}]
{4, 4, 4, 4, 4}
Table[b, {5}]
{10, 5, 2, 1, 3}
上面的示例可能会给人一种印象,即一旦使用Set
创建符号定义,其值就会固定,并且不会更改。事实并非如此。
f = ...
在分配时评估时为f
分配一个表达式。如果符号保留在该计算表达式中,并且稍后它们的值发生变化,f
的表观值也会发生变化。
ClearAll[f, x]
f = 2 x;
f
2 x
x = 7;
f
14
x = 3;
f
6
记住规则在内部的存储方式很有用。对于分配值为symbol = expression
的符号,规则存储在OwnValues
中。通常(但不总是),OwnValues
只包含一条规则。在这种特殊情况下,
In[84]:= OwnValues[f]
Out[84]= {HoldPattern[f] :> 2 x}
现在我们的重要部分是r.h.s.,它包含x
作为符号。对评估真正重要的是这种形式 - 规则在内部存储的方式。只要x
在分配时没有值,Set
和SetDelayed
都会在全局规则库中生成(创建)相同的规则,这就是全部事项。因此,它们在这方面是等同的。
最终结果是符号f
,它具有类似函数的行为,因为其计算值取决于x
的当前值。但这不是一个真正的函数,因为它没有任何参数,只触发符号x
的更改。通常,不应该使用这样的结构,因为对于全局符号(变量)的隐式依赖在Mathematica中与在其他语言中一样糟糕 - 它们使代码更难理解,并且错误更容易被忽略。可以找到一些相关的讨论here。
Set
可用于函数,有时需要它。让我给你举个例子。在这里,Mathematica象征性地求解和,然后将其分配给aF(x),然后将其用于绘图。
ClearAll[aF, x]
aF[x_] = Sum[x^n Fibonacci[n], {n, 1, \[Infinity]}];
DiscretePlot[aF[x], {x, 1, 50}]
另一方面,如果您尝试使用SetDelayed
,则将每个值传递给Sum
函数。这不仅会慢很多,但至少在Mathematica 7上,它完全失败了。
ClearAll[aF, x]
aF[x_] := Sum[x^n Fibonacci[n], {n, 1, \[Infinity]}];
DiscretePlot[aF[x], {x, 1, 50}]
如果要确保形式参数的可能全局值(此处为x
)不会干扰并在定义新函数的过程中被忽略,则Clear
的替代方法是Block
围绕定义:
ClearAll[aF, x];
x = 1;
Block[{x}, aF[x_] = Sum[x^n Fibonacci[n], {n, 1, \[Infinity]}]];
查看函数的定义可以确认我们得到了我们想要的东西:
?aF
Global`aF
aF[x_]=-(x/(-1+x+x^2))
答案 1 :(得分:9)
In[1]:= Attributes[Set]
Out[1]= {HoldFirst, Protected, SequenceHold}
In[2]:= Attributes[SetDelayed]
Out[2]= {HoldAll, Protected, SequenceHold}
正如您可以通过它们的属性看到的,两个函数都拥有它们的第一个参数(您要分配的符号),但它们的不同之处在于SetDelayed也保存其第二个参数,而Set则不包含。这意味着Set将在进行赋值时评估=
右侧的表达式。在实际使用变量之前,SetDelayed不会对:=
右侧的表达式求值。
如果作业的右侧有副作用(例如Print []),发生的事情会更清楚:
In[3]:= x = (Print["right hand side of Set"]; 3)
x
x
x
During evaluation of In[3]:= right hand side of Set
Out[3]= 3
Out[4]= 3
Out[5]= 3
Out[6]= 3
In[7]:= x := (Print["right hand side of SetDelayed"]; 3)
x
x
x
During evaluation of In[7]:= right hand side of SetDelayed
Out[8]= 3
During evaluation of In[7]:= right hand side of SetDelayed
Out[9]= 3
During evaluation of In[7]:= right hand side of SetDelayed
Out[10]= 3
答案 2 :(得分:3)
:=
用于定义函数,=
用于设置值,基本上。
即:=
将评估其读取时间,=
将在设置时进行评估。
x = 2
y = x
z := x
x = 4
现在,如果在y仍为2的情况下进行评估,则z为4