12

这个讨论出现在上一个问题中,我很想知道两者之间的区别。带有示例的插图会很好。

4

3 回答 3

16

基本示例

这是 Leonid Shifrin 的书Mathematica Programming: an Advanced Introduction 中的一个例子

这是解决此类问题的绝佳资源。见:(1) (2)

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
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在分配时没有值,两者都会在全局规则库SetSetDelayed产生(创建)相同的规则,这就是最重要的。因此,它们在这种情况下是等价的。

最终结果是一个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))
于 2011-03-16T02:22:20.677 回答
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
于 2011-03-16T03:27:51.317 回答
3

:=基本上是用于定义功能并=用于设置值。

ie:=将在读取时=评估,将在设置时评估。

想一想:

x = 2
y = x
z := x
x = 4

现在,如果在 y 仍为 2 时进行评估,则 z 为 4

于 2011-03-16T02:20:58.680 回答