防止对 Mathematica 表达式求值 [英] Preventing evaluation of Mathematica expressions

查看:28
本文介绍了防止对 Mathematica 表达式求值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

  1. 延迟[]
  2. 未评估[]
  3. HoldForm[]

有时我仍然无法在这些选项之间进行选择(并且根据对之前提到的问题的回答判断,选择是对其他人也不总是很清楚).有人能写清楚这三种方法的用法吗?

<小时>

还有其他三个包装器按住[],HoldPattern[],HoldComplete[],以及函数的各种 AttributesHoldAllHoldFirstHoldRest 和数字版本 NHold* 如果你愿意也可以讨论!>

编辑

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

<块引用>

Defer[expr] 返回一个对象保持不变,直到明确提供为 Mathematica输入,并使用评估Shift+Enter、原位评估等

解决方案

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

长话短说,Hold 用于保存在多次求值之间(无限期,直到我们需要它)之间未求值的表达式,是一个可见的包装器,即 Depth[Hold[{1,2,3}]]Depth[{1,2,3}] 不一样(这当然是求值的结果),并且通常没什么特别的 - 只是一个带有 HoldAll 属性的包装器,就像其他任何东西一样,除了作为官方"保持包装器并且与系统的其余部分集成得更好,因为许多系统功能使用或期待它.

OTOH,Unevaluated[expr] 用于临时,仅一次,弥补函数封闭表达式 expr 缺失的 Hold* 属性.虽然导致需要此封闭函数保持 expr 的行为,就好像它具有 Hold* - 属性一样,Unevaluated 属于参数,并且对于单个评估,它只工作一次,因为它在这个过程中被剥离了.此外,因为它被剥离了,所以它通常对周围的包装器是不可见的,不像 Hold.最后,它是极少数的魔法符号"之一,与 SequenceEvaluate 一起——它们深深地连接到系统中,不能轻易复制或阻止,与 Hold 不同 - 从这个意义上说,Unevaluated 更为基础.

HoldComplete 用于阻止评估过程的某些阶段,而 Hold 不会阻止.这包括拼接序列,例如:

In[25]:= {Hold[Sequence[1, 2]], HoldComplete[Sequence[1, 2]]}Out[25]= {Hold[1, 2], HoldComplete[Sequence[1, 2]]},

搜索UpValues,例如

输入[26]:=清除所有[f];f/: 保持[f[x_]] := f[x];f[x_] := x^2;在[29]:= {Hold[f[5]], HoldComplete[f[5]]},Out[29]= {25, HoldComplete[f[5]]}

和对Evaluate的免疫:

输入[33]:=清除所有[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 版编写,但大多数(如果不是全部)的讨论今天仍然有效.唉,它已经绝版了,但你可能会在亚马逊上有一些运气(就像我几年前那样).

In a recent SO question three different answers were supplied each using a different method of preventing the evaluation of the Equal[] expression. They were

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

Sometimes I still have trouble choosing between these options (and judging by answers to the before mentioned question, the choice isn't always clear for other people either). Can someone write a clear exposition on the use of these three methods?


There are three other wrappers Hold[], HoldPattern[], HoldComplete[], and the various Attributes for functions HoldAll, HoldFirst, HoldRest and the numeric versions NHold* that can also be discussed if you wish!

Edit

I just noticed that this is basically a repeat of the old question (which I had already upvoted, just forgotten...). The accepted answer linked to this talk at the 1999 Mathematica Developer Conference, which doesn't discuss Defer since it is "New in 6". Defer is more closely linked to the frontend than the other evaluation control mechanisms. It is used to create an unevaluated output that will be evaluated if supplied in and Input expression. To quote the Documentation Center:

Defer[expr] returns an object which remains unchanged until it is explicitly supplied as Mathematica input, and evaluated using Shift+Enter, Evaluate in Place, etc.

解决方案

Not touching Defer, since I did not work much with it and feel that in any given case its behavior can be reproduced by other mentioned wrappers, and discussing Hold instead on HoldForm (the difference is really in the way they are printed), here is the link to a mathgroup post where I gave a rather extensive explanation of differences between Hold and Unevaluated, including differences in usage and in the evaluation process (my second and third posts in particular).

To put the long story short, Hold is used to preserve an expression unevaluated in between several evaluations (for indefinite time, until we need it), is a visible wrapper in the sense that say Depth[Hold[{1,2,3}]] is not the same as Depth[{1,2,3}] (this is of course a consequence of evaluation), and is generally nothing special - just a wrapper with HoldAll attribute like any other, except being an "official" holding wrapper and being integrated much better with the rest of the system, since many system functions use or expect it.

OTOH, Unevaluated[expr] is used to temporarily, just once, make up for a missing Hold* attribute for a function enclosing expression expr. While resulting in behavior which would require this enclosing function to hold expr as if it had Hold* - attribute, Unevaluated belongs to the argument, and works only once, for a single evaluation, since it gets stripped in the process. Also, because it gets stripped, it often is invisible for the surrounding wrappers, unlike Hold. Finally, it is one of a very few "magic symbols", along with Sequence and Evaluate - these are deeply wired into the system and can not be easily replicated or blocked, unlike Hold - in that sense, Unevaluated is more fundamental.

HoldComplete is used when one wants to prevent certain stages of evaluation process, which Hold does not prevent. This includes splicing sequences, for example:

In[25]:= {Hold[Sequence[1, 2]], HoldComplete[Sequence[1, 2]]}

Out[25]= {Hold[1, 2], HoldComplete[Sequence[1, 2]]},

search for UpValues, for example

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]]}

and immunity to 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]]]}   

In other words, it is used when you want to prevent any evaluation of the expression inside, whatsoever. Like Hold, HoldComplete is nothing special in the sense that it is just an "official" wrapper with HoldAllComplete attribute, and you can make your own which would behave similarly.

Finally, HoldPattern is a normal (usual) head with HoldAll attribute for the purposes of evaluation, but its magic shows in the pattern-matching: it is invisible to the pattern-matcher, and is very important ingredient of the language since it allows pattern-matcher to be consistent with the evaluation process. Whenever there is a danger that the pattern in some rule may evaluate, HoldPattern can be used to ensure that this won't happen, while the pattern remains the same for the pattern-matcher. One thing I'd stress here that this is the only purpose for it. Often people use it also as an escape mechanism for the pattern-matcher, where Verbatim must be used instead. This works, but is conceptually wrong.

One very good account on evaluation process and all these things is a book of David Wagner, Power programming with Mathematica - the kernel, which was written in 1996 for version 3, but most if not all of the discussion there remains valid today. It is out of print alas, but you might have some luck on Amazon (as I had a few years ago).

这篇关于防止对 Mathematica 表达式求值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆