Set(=)和SetDelayed(:=)之间有什么区别?

时间:2011-03-16 02:17:46

标签: function wolfram-mathematica assignment-operator

这个讨论出现在previous question中,我很想知道两者之间的区别。举例说明会很好。

3 个答案:

答案 0 :(得分:16)

基本示例

以下是Leonid Shifrin的书Mathematica programming: an advanced introduction

中的一个例子

这是一个很好的资源来解决这类问题。请参阅:(1) (2)

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在分配时没有值,SetSetDelayed都会在全局规则库中生成(创建)相同的规则,这就是全部事项。因此,它们在这方面是等同的。

最终结果是符号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}]

enter image description here

另一方面,如果您尝试使用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