防止评估Mathematica表达式

Sim*_*mon 15 wolfram-mathematica

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

  1. Defer[]
  2. Unevaluated[]
  3. HoldForm[]

有时我仍然无法在这些选项之间进行选择(并且根据前面提到的问题的答案判断,对于其他人来说,选择并不总是清楚的).有人能否就这三种方法的使用写清楚的说明?


还有其他三个包装 Hold[], HoldPattern[], HoldComplete[],和各种Attributes的功能 HoldAll,HoldFirst,HoldRest和数字版本,NHold*即也可以讨论,如果你想!

编辑

我只是注意到这基本上是旧问题的重复(我已经投了很多,只是忘了...).在1999年Mathematica开发者大会上,这个讲话被接受的答案Defer与之相关,因为它是"6中的新人".Defer与其他评估控制机制相比,它与前端的联系更紧密.它用于创建未评估的输出,如果提供和Input表达式,将对其进行评估.引用文档中心:

Defer [expr]返回一个保持不变的对象,直到它作为Mathematica输入显式提供,并使用Shift + Enter,就地评估等进行评估.

Leo*_*rin 12

没有触及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]]},
Run Code Online (Sandbox Code Playgroud)

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]]}
Run Code Online (Sandbox Code Playgroud)

和免疫力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]]]}   
Run Code Online (Sandbox Code Playgroud)

换句话说,当您想要阻止对内部表达式进行任何评估时,都会使用它.就像Hold,HoldComplete它只是一个带有HoldAllComplete属性的"官方"包装器,并没有什么特别之处,你可以创建自己的行为类似的东西.

最后,HoldPattern是一个正常(通常)头部,具有HoldAll用于评估目的的属性,但它的魔术在模式匹配中显示:它对模式匹配器是不可见的,并且是语言的非常重要的组成部分,因为它允许模式匹配器与评估过程保持一致.只要存在某些规则中的模式可能会评估的危险,HoldPattern就可以用来确保不会发生这种情况,而模式匹配器的模式保持不变.我要强调的一点是,这是它的唯一目的.通常人们也将它用作模式匹配器的转义机制,Verbatim必须使用它.这有效,但在概念上是错误的.

关于评估过程和所有这些事情的一个非常好的描述是David Wagner的书,Mathematica的Power编程 - 内核,它是在1996年为版本3编写的,但是大多数(如果不是全部)讨论在今天仍然有效.这是绝版的唉,但你可能在亚马逊上有一些运气(就像我几年前一样).


Pil*_*lsy 5

Leonid Shifrin的答案相当不错,但我想触及Defer,这对于一件事情来说真的很有用.在某些情况下,很高兴能够直接构造不会被评估的表达式,但用户将能够轻松编辑; 这种行为的基本示例是按钮调色板,您可以使用它将表达式或表达式模板插入到输入单元格中,然后用户可以根据需要进行编辑.这不是唯一的方法,对于一些更复杂的应用程序,你需要进入毛茸茸的世界MakeBoxes,但基础知识Defer将很好地服务.