В чем разница между Set (=) и SetDelayed (: =)? - PullRequest
12 голосов
/ 16 марта 2011

Эта дискуссия возникла в предыдущем вопросе , и мне интересно узнать разницу между ними.Иллюстрация с примером была бы хороша.

Ответы [ 3 ]

16 голосов
/ 16 марта 2011

Базовый пример

Вот пример из книги Леонида Шифрина Программирование в Mathematica: расширенное введение

Это отличный ресурс для такого рода вопросов. См .: (1) (2)

ClearAll[a, b]

a = RandomInteger[{1, 10}];

b := RandomInteger[{1, 10}]
Table[a, {5}]
<b>  {4, 4, 4, 4, 4}</b>
Table[b, {5}]
<b>  {10, 5, 2, 1, 3}</b>

Сложный пример

Приведенный выше пример может создать впечатление, что после создания определения символа с использованием Set его значение является фиксированным и не изменяется. Это не так.

f = ... присваивает f выражение, которое оценивает во время присваивания . Если символы остаются в этом вычисленном выражении, а затем их значения изменяются, то же самое происходит и с видимым значением f.

ClearAll[f, x]

f = 2 x;
f
<b>  2 x</b>
x = 7;
f
<b>  14</b>
x = 3;
f
<b>  6</b>

Полезно иметь в виду, как правила хранятся внутри. Для символов, которым присвоено значение 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 символически решает сумму, а затем присваивает ее aF (x), которая затем используется для построения графика.

ClearAll[aF, x]

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

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

enter image description here

Если, с другой стороны, вы пытаетесь использовать 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))
9 голосов
/ 16 марта 2011
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 голосов
/ 16 марта 2011

:= для определения функций и = для установки значения, в основном.

т.е. := будет оценивать, когда его чтение, = будет оцениваться, когда оно установлено.1007 *

подумайте о:

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

Теперь z равно 4, если вычислено, а y равно 2

...