Это обсуждение появилось в предыдущем вопросе, и мне интересно узнать разницу между ними. Иллюстрация с примером будет приятной.
В чем разница между Set (=) и SetDelayed (: =)?
Ответ 1
Основной пример
Вот пример из книги Леонида Шифрина Математическое программирование: расширенное введение
Это отличный ресурс для такого рода вопросов. Смотрите: (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}
Важной для нас сейчас является r.h.s., которая содержит 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}]
Если, с другой стороны, вы пытаетесь использовать 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))
Ответ 2
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
Ответ 3
:=
предназначен для определения функций, а =
- для установки значения в основном.
т.е. :=
будет оценивать, когда его чтение, =
будет оцениваться, когда оно установлено.
подумайте:
x = 2
y = x
z := x
x = 4
Теперь z равно 4, если оценивается, а y еще 2