Ответ 1
Не касаясь Defer
, так как я не очень много работал с ним и считаю, что в любом случае его поведение может быть воспроизведено другими упомянутыми обертками и обсуждать Hold
вместо этого на HoldForm
(разница действительно в как они печатаются), здесь - это ссылка на сообщение mathgroup, где я дал довольно подробное объяснение различий между 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 (как и несколько лет назад).