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

发布于 2024-10-21 21:50:50 字数 141 浏览 0 评论 0原文

此讨论出现在上一个问题中,我有兴趣了解之间的区别两个。举例说明会很好。

This discussion came up in a previous question and I'm interested in knowing the difference between the two. Illustration with an example would be nice.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

dawn曙光 2024-10-28 21:50:50

基本示例

是 Leonid Shifrin 的书 Mathematica 编程:高级介绍 中的示例

这 是解决此类问题的绝佳资源。请参阅:(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}

现在对我们来说重要的部分是 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))

Basic Example

Here is an example from Leonid Shifrin's book Mathematica programming: an advanced introduction

It is an excellent resource for this kind of question. See: (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}

Complicated Example

The example above may give the impression that once a definition for a symbol is created using Set, its value is fixed, and does not change. This is not so.

f = ... assigns to f an expression as it evaluates at the time of assignment. If symbols remain in that evaluated expression, and later their values change, so does the apparent value of f.

ClearAll[f, x]

f = 2 x;
f
  2 x
x = 7;
f
  14
x = 3;
f
  6

It is useful to keep in mind how the rules are stored internally. For symbols assigned a value as symbol = expression, the rules are stored in OwnValues. Usually (but not always), OwnValues contains just one rule. In this particular case,

In[84]:= OwnValues[f]

Out[84]= {HoldPattern[f] :> 2 x}

The important part for us now is the r.h.s., which contains x as a symbol. What really matters for evaluation is this form - the way the rules are stored internally. As long as x did not have a value at the moment of assignment, both Set and SetDelayed produce (create) the same rule above in the global rule base, and that is all that matters. They are, therefore, equivalent in this context.

The end result is a symbol f that has a function-like behavior, since its computed value depends on the current value of x. This is not a true function however, since it does not have any parameters, and triggers only changes of the symbol x. Generally, the use of such constructs should be discouraged, since implicit dependencies on global symbols (variables) are just as bad in Mathematica as they are in other languages - they make the code harder to understand and bugs subtler and easier to overlook. Somewhat related discussion can be found here.


Set used for functions

Set can be used for functions, and sometimes it needs to be. Let me give you an example. Here Mathematica symbolically solves the Sum, and then assigns that to aF(x), which is then used for the plot.

ClearAll[aF, x]

aF[x_] = Sum[x^n Fibonacci[n], {n, 1, \[Infinity]}];

DiscretePlot[aF[x], {x, 1, 50}]

enter image description here

If on the other hand you try to use SetDelayed then you pass each value to be plotted to the Sum function. Not only will this be much slower, but at least on Mathematica 7, it fails entirely.

ClearAll[aF, x]

aF[x_] := Sum[x^n Fibonacci[n], {n, 1, \[Infinity]}];

DiscretePlot[aF[x], {x, 1, 50}]

If one wants to make sure that possible global values for formal parameters (x here) do not interfere and are ignored during the process of defining a new function, an alternative to Clear is to wrap Block around the definition:

ClearAll[aF, x];
x = 1;
Block[{x}, aF[x_] = Sum[x^n Fibonacci[n], {n, 1, \[Infinity]}]];

A look at the function's definition confirms that we get what we wanted:

?aF
Global`aF
aF[x_]=-(x/(-1+x+x^2))
指尖微凉心微凉 2024-10-28 21:50:50
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
In[1]:= Attributes[Set]

Out[1]= {HoldFirst, Protected, SequenceHold}

In[2]:= Attributes[SetDelayed]

Out[2]= {HoldAll, Protected, SequenceHold}

As you can see by their attributes, both functions hold their first argument (the symbol to which you are assigning), but they differ in that SetDelayed also holds its second argument, while Set does not. This means that Set will evaluate the expression to the right of = at the time the assignment is made. SetDelayed does not evaluate the expression to the right of the := until the variable is actually used.

What's happening is more clear if the right hand side of the assignment has a side effect (e.g. 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
淡写薰衣草的香 2024-10-28 21:50:50

基本上,:= 用于定义函数,= 用于设置值。

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

想一想:

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

现在,如果在 y 仍为 2 时求值,则 z 为 4

:= is for defining functions and = is for setting a value, basically.

ie := will evaluate when its read, = will be evaluated when it is set.

think about:

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

Now, z is 4 if evaluated while y is still 2

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文