Не трогая Defer
, так как я не очень много работал с ним и чувствую, что в любом конкретном случае его поведение может быть воспроизведено другими упомянутыми обертками, и обсуждается Hold
вместо HoldForm
(разница действительно в то, как они напечатаны), здесь - это ссылка на пост в математической группе, где я дал довольно подробное объяснение различий между Hold
и Unevaluated
, включая различия в использовании и в процессе оценки (мой второй и третий посты в частности).
Короче говоря, Hold
используется для сохранения выражения, не оцененного между несколькими оценками (в течение неопределенного времени, пока оно нам не понадобится), является видимой оболочкой в том смысле, что Depth[Hold[{1,2,3}]]
не является такой же, как Depth[{1,2,3}]
(это, конечно, следствие оценки), и, как правило, ничего особенного - просто обертка с атрибутом HoldAll
, как и любой другой, за исключением того, что она является «официальной» оберткой для хранения и гораздо лучше интегрируется с остальными системы, поскольку многие системные функции используют или ожидают ее.
OTOH, Unevaluated[expr]
используется для временного, только один раз, восполнения отсутствующего атрибута Hold * для функции, содержащей выражение expr
. В то время как в результате получается поведение, которое потребовало бы, чтобы эта вмещающая функция содержала expr
, как если бы она имела атрибут Hold*
-, Unevaluated
принадлежит аргументу и работает только один раз, для одной оценки, так как она удаляется в процессе. , Кроме того, поскольку он удаляется, он часто невидим для окружающих оболочек, в отличие от Hold
. Наконец, это один из очень немногих «магических символов», наряду с Sequence
и Evaluate
- они глубоко подключены к системе и не могут быть легко скопированы или заблокированы, в отличие от Hold
- в этом смысле Unevaluated
более фундаментально.
HoldComplete
используется, когда требуется предотвратить определенные этапы процесса оценки, что Hold
не мешает. Это включает последовательности сплайсинга, например:
In[25]:= {Hold[Sequence[1, 2]], HoldComplete[Sequence[1, 2]]}
Out[25]= {Hold[1, 2], HoldComplete[Sequence[1, 2]]},
поиск UpValues
, например
In[26]:=
ClearAll[f];
f /: Hold[f[x_]] := f[x];
f[x_] := x^2;
In[29]:= {Hold[f[5]], HoldComplete[f[5]]},
Out[29]= {25, HoldComplete[f[5]]}
и иммунитет к Evaluate
:
In[33]:=
ClearAll[f];
f[x_] := x^2;
In[35]:= {Hold[Evaluate[f[5]]], HoldComplete[Evaluate[f[5]]]}
Out[35]= {Hold[25], HoldComplete[Evaluate[f[5]]]}
Другими словами, он используется, когда вы хотите предотвратить какую-либо оценку выражения внутри. Как и Hold
, HoldComplete
не является чем-то особенным в том смысле, что это просто «официальная» оболочка с атрибутом HoldAllComplete
, и вы можете создать свою собственную, которая будет вести себя аналогично.
Наконец, HoldPattern
- это обычная (обычная) голова с атрибутом HoldAll
для целей оценки, но ее магия проявляется в сопоставлении с образцом: она невидима для сопоставителя с образцом и является очень важным компонентом языка, так как он позволяет шаблону сопоставления с процессом оценки. Всякий раз, когда существует опасность, что шаблон в каком-либо правиле может быть оценен, можно использовать HoldPattern
, чтобы гарантировать, что этого не произойдет, в то время как шаблон остается таким же для сопоставителя шаблонов. Здесь я бы хотел подчеркнуть, что это единственная цель. Часто люди используют его также в качестве механизма экранирования для сопоставления с образцом, где вместо него следует использовать Verbatim
. Это работает, но концептуально неверно.
Один очень хороший отчет о процессе оценки и обо всех этих вещах - книга Дэвида Вагнера, Мощное программирование с Mathematica - ядром , которое было написано в 1996 году для версии 3, но большинство, если не все, обсуждение там остается в силе сегодня. Увы, он распечатан, но вам, возможно, повезет на Amazon (как я это сделал несколько лет назад).