12 wolfram-mathematica function assignment-operator
这个讨论出现在之前的问题中,我很想知道两者之间的区别.举例说明会很好.
Mr.*_*ard 16
以下是Leonid Shifrin的书Mathematica编程的一个例子:高级介绍
ClearAll[a, b]
a = RandomInteger[{1, 10}];
b := RandomInteger[{1, 10}]
Run Code Online (Sandbox Code Playgroud)
Table[a, {5}]
{4, 4, 4, 4, 4}
Table[b, {5}]
Run Code Online (Sandbox Code Playgroud)
{10, 5, 2, 1, 3}
上面的示例可能给人的印象是,一旦使用创建符号的定义Set
,其值就是固定的,并且不会改变.事实并非如此.
f = ...
分配给f
一个表达式,因为它的计算结果在分配时.如果符号保留在该计算表达式中,并且稍后它们的值发生变化,则表观值也会发生变化f
.
ClearAll[f, x]
f = 2 x;
f
Run Code Online (Sandbox Code Playgroud)
2 x
x = 7;
f
Run Code Online (Sandbox Code Playgroud)
14
x = 3;
f
Run Code Online (Sandbox Code Playgroud)
6
记住规则如何在内部存储是很有用的.对于赋值为的符号symbol = expression
,规则存储在OwnValues
.通常(但不总是),OwnValues
只包含一个规则.在这种特殊情况下,
In[84]:= OwnValues[f]
Out[84]= {HoldPattern[f] :> 2 x}
Run Code Online (Sandbox Code Playgroud)
现在我们的重要部分是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}]
Run Code Online (Sandbox Code Playgroud)
另一方面,如果您尝试使用,SetDelayed
则将每个值传递给Sum
函数.这不仅会慢很多,但至少在Mathematica 7上,它完全失败了.
ClearAll[aF, x]
aF[x_] := Sum[x^n Fibonacci[n], {n, 1, \[Infinity]}];
DiscretePlot[aF[x], {x, 1, 50}]
Run Code Online (Sandbox Code Playgroud)
如果要确保形式参数的可能全局值(x
此处)不会干扰并在定义新函数的过程中被忽略,则替代方法Clear
是包围Block
定义:
ClearAll[aF, x];
x = 1;
Block[{x}, aF[x_] = Sum[x^n Fibonacci[n], {n, 1, \[Infinity]}]];
Run Code Online (Sandbox Code Playgroud)
查看函数的定义可以确认我们得到了我们想要的东西:
?aF
Global`aF
aF[x_]=-(x/(-1+x+x^2))
Run Code Online (Sandbox Code Playgroud)
In[1]:= Attributes[Set]
Out[1]= {HoldFirst, Protected, SequenceHold}
In[2]:= Attributes[SetDelayed]
Out[2]= {HoldAll, Protected, SequenceHold}
Run Code Online (Sandbox Code Playgroud)
正如你可以通过它们的属性看到的那样,两个函数都拥有它们的第一个参数(你要分配的符号),但它们的不同之处在于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
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
1309 次 |
最近记录: |