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

时间:2022-06-20 13:25:30

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.

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

3 个解决方案

#1


16  

Basic Example

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

以下是Leonid Shifrin的书Mathematica编程的一个例子:高级介绍

It is an excellent resource for this kind of question. See: (1) (2)

对于这类问题,它是一个很好的资源。见:(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.

上面的示例可能会给人一种印象,即一旦使用Set创建符号的定义,其值就会固定,并且不会更改。事实并非如此。

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.

f = ...在赋值时计算表达式。如果符号保留在该计算表达式中,并且稍后它们的值发生变化,则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,

记住规则如何在内部存储是很有用的。对于将值指定为symbol = expression的符号,规则存储在OwnValues中。通常(但不总是),OwnValues只包含一个规则。在这种特殊情况下,

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.

现在我们的重要部分是r.h.s.,它包含x作为符号。对评估真正重要的是这种形式 - 规则在内部存储的方式。只要x在赋值时没有值,Set和SetDelayed就会在全局规则库中生成(创建)上面相同的规则,这就是最重要的。因此,它们在这方面是等同的。

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.

最终结果是具有类似函数行为的符号f,因为其计算值取决于x的当前值。然而,这不是真正的函数,因为它没有任何参数,并且仅触发符号x的更改。一般来说,不应该使用这样的结构,因为对于全局符号(变量)的隐式依赖在Mathematica中与在其他语言中一样糟糕 - 它们使代码更难理解,并且错误更容易被忽略。在这里可以找到一些相关的讨论。


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.

Set可用于功能,有时需要。让我举一个例子。在这里,Mathematica象征性地求解Sum,然后将其分配给aF(x),然后将其用于绘图。

ClearAll[aF, x]

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

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

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

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.

另一方面,如果您尝试使用SetDelayed,则将每个值传递给Sum函数。这不仅会慢很多,但至少在Mathematica 7上,它完全失败了。

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:

如果想要确保形式参数的可能全局值(此处为x)不会干扰并在定义新函数的过程中被忽略,则Clear的替代方法是将Block包围在定义周围:

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))

#2


9  

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.

正如你可以通过它们的属性看到的那样,两个函数都保存着它们的第一个参数(你要指定的符号),但它们的不同之处在于SetDelayed也保存了它的第二个参数,而Set则没有。这意味着Set将在分配时评估=右侧的表达式。 SetDelayed不会计算:=右边的表达式,直到实际使用该变量。

What's happening is more clear if the right hand side of the assignment has a side effect (e.g. Print[]):

如果作业的右侧有副作用(例如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

#3


3  

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

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

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

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

think about:

想一想:

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

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

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

#1


16  

Basic Example

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

以下是Leonid Shifrin的书Mathematica编程的一个例子:高级介绍

It is an excellent resource for this kind of question. See: (1) (2)

对于这类问题,它是一个很好的资源。见:(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.

上面的示例可能会给人一种印象,即一旦使用Set创建符号的定义,其值就会固定,并且不会更改。事实并非如此。

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.

f = ...在赋值时计算表达式。如果符号保留在该计算表达式中,并且稍后它们的值发生变化,则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,

记住规则如何在内部存储是很有用的。对于将值指定为symbol = expression的符号,规则存储在OwnValues中。通常(但不总是),OwnValues只包含一个规则。在这种特殊情况下,

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.

现在我们的重要部分是r.h.s.,它包含x作为符号。对评估真正重要的是这种形式 - 规则在内部存储的方式。只要x在赋值时没有值,Set和SetDelayed就会在全局规则库中生成(创建)上面相同的规则,这就是最重要的。因此,它们在这方面是等同的。

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.

最终结果是具有类似函数行为的符号f,因为其计算值取决于x的当前值。然而,这不是真正的函数,因为它没有任何参数,并且仅触发符号x的更改。一般来说,不应该使用这样的结构,因为对于全局符号(变量)的隐式依赖在Mathematica中与在其他语言中一样糟糕 - 它们使代码更难理解,并且错误更容易被忽略。在这里可以找到一些相关的讨论。


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.

Set可用于功能,有时需要。让我举一个例子。在这里,Mathematica象征性地求解Sum,然后将其分配给aF(x),然后将其用于绘图。

ClearAll[aF, x]

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

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

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

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.

另一方面,如果您尝试使用SetDelayed,则将每个值传递给Sum函数。这不仅会慢很多,但至少在Mathematica 7上,它完全失败了。

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:

如果想要确保形式参数的可能全局值(此处为x)不会干扰并在定义新函数的过程中被忽略,则Clear的替代方法是将Block包围在定义周围:

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))

#2


9  

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.

正如你可以通过它们的属性看到的那样,两个函数都保存着它们的第一个参数(你要指定的符号),但它们的不同之处在于SetDelayed也保存了它的第二个参数,而Set则没有。这意味着Set将在分配时评估=右侧的表达式。 SetDelayed不会计算:=右边的表达式,直到实际使用该变量。

What's happening is more clear if the right hand side of the assignment has a side effect (e.g. Print[]):

如果作业的右侧有副作用(例如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

#3


3  

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

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

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

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

think about:

想一想:

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

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

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