这个讨论出现在上一个问题中,我很想知道两者之间的区别。带有示例的插图会很好。
3 回答
基本示例
这是 Leonid Shifrin 的书Mathematica Programming: an Advanced Introduction 中的一个例子
ClearAll[a, b]
a = RandomInteger[{1, 10}];
b := RandomInteger[{1, 10}]
表[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 = 7;
f
14
x = 3;
f
6
记住规则是如何在内部存储的很有用。对于赋值为 的符号symbol = expression
,规则存储在OwnValues
. 通常(但不总是)OwnValues
只包含一个规则。在这种特殊情况下,
In[84]:= OwnValues[f]
Out[84]= {HoldPattern[f] :> 2 x}
现在对我们来说重要的部分是 rhs,它包含x
一个符号。评估真正重要的是这种形式——规则在内部存储的方式。只要x
在分配时没有值,两者都会在全局规则库Set
中SetDelayed
产生(创建)相同的规则,这就是最重要的。因此,它们在这种情况下是等价的。
最终结果是一个f
具有类似函数行为的符号,因为它的计算值取决于 的当前值x
。然而,这不是一个真正的函数,因为它没有任何参数,并且仅触发符号的更改x
。一般来说,不鼓励使用这种结构,因为对全局符号(变量)的隐式依赖在 Mathematica 中和在其他语言中一样糟糕——它们使代码更难理解,错误更微妙,更容易被忽视。可以在这里找到一些相关的讨论。
用于功能的集合
Set
可用于函数,有时需要。让我给你举个例子。在这里,Mathematica 象征性地求解 Sum,然后将其分配给 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))
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
:=
基本上是用于定义功能并=
用于设置值。
ie:=
将在读取时=
评估,将在设置时评估。
想一想:
x = 2
y = x
z := x
x = 4
现在,如果在 y 仍为 2 时进行评估,则 z 为 4