在最近的SO question中,提供了三个不同的答案,每个答案使用不同的方法来阻止评估Equal[]
表达式。他们是
Defer[]
Unevaluated[]
HoldForm[]
有时我仍然无法在这些选项之间进行选择(并且根据before mentioned question的答案来判断,对于其他人来说,选择并不总是清楚的)。有人能否清楚地阐述这三种方法的用途?
还有其他三个包装器
Hold[]
,
HoldPattern[]
,
HoldComplete[]
,
以及函数的各种Attributes
HoldAll
,HoldFirst
,HoldRest
以及数字版本NHold*
,如果您愿意,也可以进行讨论!
我只是注意到这基本上是旧question的重复(我已经投票,只是忘了...)。在1999年Mathematica开发者大会上,this talk接受的答案与Defer
有关,因为它是“新的6”。与其他评估控制机制相比,Defer
与前端的联系更紧密。它用于创建未评估的输出,如果在Input
表达式中提供,将对其进行评估。引用Documentation Center:
Defer [expr]返回一个对象 在此之前保持不变 明确提供为Mathematica 输入,并使用评估 Shift + Enter,就地评估等
答案 0 :(得分:12)
没有触及Defer
,因为我对它没有多大帮助,并且觉得在任何特定情况下,其行为可以由其他提到的包装器重现,并在Hold
上讨论HoldForm
(区别在于它们的打印方式),here是数学组帖子的链接,我对Hold
和Unevaluated
之间的差异进行了相当广泛的解释,包括用法和评估过程(特别是我的第二和第三个帖子)。
长话短说,Hold
用于保存在几次评估之间未评估的表达式(无限期,直到我们需要它),是{{1}的意义上的可见包装器。 }与Depth[Hold[{1,2,3}]]
不同(这当然是评估的结果),并且通常没什么特别的 - 只是一个与Depth[{1,2,3}]
属性一样的包装器,除了是一个“官方”持有包装器由于许多系统功能使用或期望它,因此与系统的其他部分集成得更好。
OTOH,HoldAll
用于暂时,仅一次,弥补包含表达式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
。这有效,但在概念上是错误的。
关于评估过程的一个非常好的说明,所有这些都是David Wagner的书,使用Mathematica进行Power编程 - 内核,它是在1996年为版本3编写的,但大多数(如果不是全部的话)今天的讨论仍然有效。这是绝版的唉,但你可能在亚马逊上有一些运气(就像我几年前那样)。
答案 1 :(得分:5)
Leonid Shifrin's回答非常好,但我想触及Defer
,这对一件事情非常有用。在某些情况下,很高兴能够直接构造不会被评估的表达式,但用户将能够轻松编辑;这种行为的基本示例是按钮调色板,您可以使用它将表达式或表达式模板插入到输入单元格中,然后用户可以根据需要进行编辑。这不是唯一的方法,对于一些更复杂的应用程序,您需要进入毛茸茸的世界MakeBoxes
,但基础知识Defer
将很好地服务。