この議論は前の質問で出てきました.2つの違いを知りたいです. 例のイラストがいいでしょう。
3 に答える
基本的な例
Leonid Shifrin の著書Mathematica プログラミングからの例を次に示します。
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
1 つのルールのみが含まれます。この特定のケースでは、
In[84]:= OwnValues[f]
Out[84]= {HoldPattern[f] :> 2 x}
x
現在、私たちにとって重要な部分は、シンボルとして含まれている rhsです。評価にとって本当に重要なのは、この形式、つまりルールが内部に保存される方法です。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 は 2 番目の引数も保持し、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
:=
基本的に、関数を定義するためのもの=
であり、値を設定するためのものです。
つまり:=
、読み取り時に=
評価され、設定時に評価されます。
について考える:
x = 2
y = x
z := x
x = 4
ここで、y がまだ 2 であるときに評価すると、z は 4 です。