【问题标题】:Preventing evaluation of Mathematica expressions防止对 Mathematica 表达式求值
【发布时间】:2011-01-31 21:13:27
【问题描述】:

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

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

有时我仍然无法在这些选项之间进行选择(根据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、原地求值等

【问题讨论】:

  • 感谢您提醒我有关该来源的信息。早就知道了,但从来没有真正找到时间仔细研究它。我从不同的来源了解到这一点,所以我没有想到这个参考,虽然它可能比我给出的更相关。
  • @Simon - 这也在我的某个地方。神奇地恰好是我正在做的事情(错误,应该在做)。

标签: wolfram-mathematica


【解决方案1】:

没有接触Defer,因为我没有用它做太多工作,并且觉得在任何给定的情况下它的行为都可以被其他提到的包装器复制,并在HoldForm 上讨论Hold(区别真的在于它们的打印方式),here 是指向 mathgroup 帖子的链接,我在该帖子中对HoldUnevaluated 之间的差异进行了相当广泛的解释,包括使用和评估过程中的差异(我的第二个和第三个帖子尤其)。

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

OTOH,Unevaluated[expr] 用于临时,仅一次,为包含表达式 expr 的函数弥补缺少的 Hold* 属性。虽然导致需要此封闭函数保持 expr 的行为,就好像它具有 Hold* - 属性一样,Unevaluated 属于参数,并且对于单个评估仅工作一次,因为它在过程中被剥离.此外,由于它被剥离,它通常对周围的包装是不可见的,这与Hold 不同。最后,它是极少数“神奇符号”之一,与SequenceEvaluate 一起——它们与系统紧密相连,不能轻易复制或阻止,不像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 版编写,但如果不是全部的话,也是大多数那里的讨论今天仍然有效。唉,它已经绝版了,但你可能在亚马逊上有一些运气(就像我几年前一样)。

【讨论】:

  • 我喜欢“官方”包装的短语/想法少数“神奇符号”。这些短语确实让您想起了您的数学组帖子。
  • @Simon: “魔法符号” 我从瓦格纳那里偷来的(他称它们为“魔法饼干”),“官方” 是我的 :)。实际上,他的阐述是迄今为止我所见过的最好的(没有读过 Villegas 的),尽管它可以从所涉及的微妙之处的更多插图中受益,就像我在那篇文章中给出的例子一样。
  • 谁能给我举个例子,说明使用 Defer 而不是 HoldForm 更有利?
【解决方案2】:

Leonid Shifrin's 的回答很好,但我想谈谈Defer,它只对一件事非常有用。在某些情况下,能够直接构造不会被计算但用户可以轻松编辑的表达式是很好的;这种行为的基本示例是按钮面板,您可以使用它来将表达式或表达式模板插入到输入单元格中,然后用户可以根据需要对其进行编辑。这不是唯一的方法,对于一些更复杂的应用程序,您需要进入毛茸茸的世界MakeBoxes,但对于基础知识Defer 会很好。

【讨论】:

  • 感谢您的信息。当我需要这种功能时,我通常使用盒子,但无论如何很高兴知道 - 在某些情况下使用Defer 确实更简单。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-01-04
  • 1970-01-01
  • 2015-03-29
  • 2011-12-25
  • 1970-01-01
  • 2021-11-16
  • 1970-01-01
相关资源
最近更新 更多