防止评估Mathematica表达式

时间:2011-01-31 21:13:27

标签: wolfram-mathematica

在最近的SO question中,提供了三个不同的答案,每个答案使用不同的方法来阻止评估Equal[]表达式。他们是

  1. Defer[]
  2. Unevaluated[]
  3. HoldForm[]
  4. 有时我仍然无法在这些选项之间进行选择(并且根据before mentioned question的答案来判断,对于其他人来说,选择并不总是清楚的)。有人能否清楚地阐述这三种方法的用途?


    还有其他三个包装器  Hold[],  HoldPattern[],  HoldComplete[], 以及函数的各种Attributes  HoldAllHoldFirstHoldRest以及数字版本NHold*,如果您愿意,也可以进行讨论!

    修改

    我只是注意到这基本上是旧question的重复(我已经投票,只是忘了...)。在1999年Mathematica开发者大会上,this talk接受的答案与Defer有关,因为它是“新的6”。与其他评估控制机制相比,Defer与前端的联系更紧密。它用于创建未评估的输出,如果在Input表达式中提供,将对其进行评估。引用Documentation Center

      

    Defer [expr]返回一个对象   在此之前保持不变   明确提供为Mathematica   输入,并使用评估   Shift + Enter,就地评估等

2 个答案:

答案 0 :(得分:12)

没有触及Defer,因为我对它没有多大帮助,并且觉得在任何特定情况下,其行为可以由其他提到的包装器重现,并在Hold上讨论HoldForm (区别在于它们的打印方式),here是数学组帖子的链接,我对HoldUnevaluated之间的差异进行了相当广泛的解释,包括用法和评估过程(特别是我的第二和第三个帖子)。

长话短说,Hold用于保存在几次评估之间未评估的表达式(无限期,直到我们需要它),是{{1}的意义上的可见包装器。 }与Depth[Hold[{1,2,3}]]不同(这当然是评估的结果),并且通常没什么特别的 - 只是一个与Depth[{1,2,3}]属性一样的包装器,除了是一个“官方”持有包装器由于许多系统功能使用或期望它,因此与系统的其他部分集成得更好。

OTOH,HoldAll用于暂时,仅一次,弥补包含表达式Unevaluated[expr]的函数的缺失Hold *属性。虽然导致行为需要此封闭函数保持expr,就像它具有expr - 属性一样,Hold*属于参数,并且只能运行一次,用于单个评估,因为它在这个过程中被剥夺了。此外,由于它被剥离,因此与Unevaluated不同,它通常对周围的包装器不可见。最后,它是极少数“魔术符号”之一,与HoldSequence一起 - 它们与系统深度连接,无法轻易复制或阻止,与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将很好地服务。