没有接触Defer,因为我没有用它做太多工作,并且觉得在任何给定的情况下它的行为都可以被其他提到的包装器复制,并在HoldForm 上讨论Hold(区别真的在于它们的打印方式),here 是指向 mathgroup 帖子的链接,我在该帖子中对Hold 和Unevaluated 之间的差异进行了相当广泛的解释,包括使用和评估过程中的差异(我的第二个和第三个帖子尤其)。
长话短说,Hold 用于保存在多次评估之间未评估的表达式(无限期,直到我们需要它),在某种意义上说 Depth[Hold[{1,2,3}]] 不是与Depth[{1,2,3}] 相同(这当然是评估的结果),并且通常没有什么特别之处 - 只是一个具有HoldAll 属性的包装器,就像其他任何东西一样,除了作为“官方”持有包装器并且与其余部分更好地集成系统,因为许多系统功能使用或期望它。
OTOH,Unevaluated[expr] 用于临时,仅一次,为包含表达式 expr 的函数弥补缺少的 Hold* 属性。虽然导致需要此封闭函数保持 expr 的行为,就好像它具有 Hold* - 属性一样,Unevaluated 属于参数,并且对于单个评估仅工作一次,因为它在过程中被剥离.此外,由于它被剥离,它通常对周围的包装是不可见的,这与Hold 不同。最后,它是极少数“神奇符号”之一,与Sequence 和Evaluate 一起——它们与系统紧密相连,不能轻易复制或阻止,不像Hold——从这个意义上说,@ 987654340@ 更基础。
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。这可行,但在概念上是错误的。
关于评估过程和所有这些事情的一个很好的说明是 David Wagner 的一本书,Power Programming with Mathematica - the kernel,该书于 1996 年为第 3 版编写,但如果不是全部的话,也是大多数那里的讨论今天仍然有效。唉,它已经绝版了,但你可能在亚马逊上有一些运气(就像我几年前一样)。