在 Mathematica 中的 Hold 中评估超过一级
关于 Evaluate at possible issues 的 mathematica 文档说:
仅评估第一个作品 级别,直接在持有的函数内
为什么 Mathematica 有这个限制?因此,如果我有一个以上级别的表达式,请采用以下简化示例:
Hold[Plus[Plus[2, 2], 2]]]
现在假设我想看看第二个 Plus 的答案是什么,而不评估任何内容在低于它的水平上。我尝试过不同的事情,例如:
In[290]:= Hold[Plus[Evaluate[Plus[2, 2]], 2]]
Out[290]= Hold[Evaluate[2+2]+2]
In[287]:= Hold[Plus[ReleaseHold[Hold[Plus[2, 2]]], 2]]
Out[287]= Hold[ReleaseHold[Hold[2+2]]+2]
在这种情况下,第一个保留使所有内容在第一级和第一级之后都未被评估。 目标是使用连续的 Hold、ReleaseHold 和 Evaluate 函数来控制从最内层嵌套函数到外层嵌套函数的每个阶段的表达式计算。我知道我可以使用跟踪来查看表达式中第一级之后发生的情况,但这是不同的,有时用较长的表达式来读取会很复杂。
似乎唯一的方法是使用 Extract、Part 或 Level 将表达式提取并完全分解为列表;评估我想要的表达式的一部分;然后为每个阶段重建并重新映射表达式。我可以考虑其他方法或功能来实现这一目标吗?
编辑:这可能是一个更好的例子来了解释放第一个保持的方法。使用表达式:
Hold[Plus[Plus[2, Plus[2,2]], 2]]]
如果您释放第一个保留并在第三个 Plus 处的表达式中将保留置于较高级别上,则如下所示:
in = Plus[Plus[2, Hold[Plus[2,2]]], 2]]]
out = Hold[2+2]+4
您会发现,当您确实希望 Mathematica 等待时,它会在后台计算较低级别。
The mathematica documentation on Evaluate at possible issues says:
Evaluate works only on the first
level, directly inside a held function
Why does Mathematica have this limitation? So if I have an expression with more than one level take this simplified example:
Hold[Plus[Plus[2, 2], 2]]]
Now suppose I want to see what the answer is to the the second Plus, without evaluating anything on levels below it. I've tried different things such as:
In[290]:= Hold[Plus[Evaluate[Plus[2, 2]], 2]]
Out[290]= Hold[Evaluate[2+2]+2]
In[287]:= Hold[Plus[ReleaseHold[Hold[Plus[2, 2]]], 2]]
Out[287]= Hold[ReleaseHold[Hold[2+2]]+2]
The first Hold keeps everything unevaluated at and beyond the first level in this case.
The goal is to control evaluation of an expression at each stage from the most inner nested function to the outer one using successive Hold, ReleaseHold and Evaluate functions to achieve that. I know I could use trace to see what happens beyond level one in an expression but that is different and sometimes complex to read with longer expressions.
It seems like the only way is to extract and totally dismantle the expression into lists using Extract, Part or Level; evaluate part of the expression that I want; then reconstruct and re-map the expression back together for each stage. Are there any other approaches or functions for achieving this I could consider?
Edit: This might be a better example to look at the approach of releasing the first hold. With the expression:
Hold[Plus[Plus[2, Plus[2,2]], 2]]]
If you release the first hold and place a hold on a higher level in a expression at the third Plus, to look like this:
in = Plus[Plus[2, Hold[Plus[2,2]]], 2]]]
out = Hold[2+2]+4
You find that Mathematica will evaluate lower levels in the background when you really want it to wait.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我无法给出
Evaluate
“仅在第一级工作,直接在保留函数内工作”的确切原因,但我怀疑这部分是效率问题,因为如果评估器必须扫描,它会很慢传递给具有嵌套 Evaluate 表达式的Hold*
属性的任何函数的完整表达式树,并对它们进行求值,然后递归并查找Evaluate 子表达式在它刚刚计算的内容中,同时保持表达式的其余部分不计算,特别是当这可能并不总是您想要发生的情况时。
不过,使用
Extract
和ReplacePart
的组合来完成您想要的操作非常容易:这让我们说明了为什么它对于
Evaluate
可能没有意义的另一个原因> 在作为参数传递给具有Hold*
属性的函数的表达式中的任何级别上工作,考虑到以下涉及i
的表达式:请注意
的值如果我们在
将会是Plus
之前计算该表达式的第一部分,>j4
,但结果会有所不同,因为我们只进行部分计算,并且当我们计算子表达式设置j
时,尚未计算i=2
。有时,这可能是您希望发生的事情,但通常情况下它很可能不是。请记住,即使第一级中的
Evaluate
也可能被具有HoldAllComplete
属性的函数或使用HoldComplete
击败:...与:
最后,
Trace
的输出可能有点密集,但是您可以通过在第二个参数中使用感兴趣的模式或符号来过滤掉您想要的内容:HTH!
I can't give the exact reason why
Evaluate
"works only on the first level, directly inside a held function" but I suspect it's partly efficiency, in that it would be slow if the evaluator had to scan the complete expression tree of held arguments passed to any function with aHold*
attribute for nestedEvaluate
expressions and evaluate them, and then recurse and look forEvaluate
subexpressions in what it just evaluated, all while keeping the rest of the expression unevaluated, especially when this might not always be what you want to happen anyway.Doing what you want is pretty easy using a combination of
Extract
andReplacePart
though:This lets us illustrate another reason why it might not make sense for
Evaluate
to work at any level in an expression passed as an argument to a function with aHold*
attribute, considering the following expression involvingi
:Note that the value of
j
would have been4
if we had evaluated the first part of that expression before thePlus
, but the results are different since we are only doing partial evaluation, andi=2
had not been evaluated when we evaluated the subexpression settingj
. Sometimes, this may be what you want to happen, but often it is very likely not.Keep in mind that even
Evaluate
in the first level can be defeated by a function that has the attributeHoldAllComplete
or by usingHoldComplete
:...versus:
Finally, the output of
Trace
can be a little dense, but you can filter out what you want by using patterns or symbols of interest in the second argument:HTH!
当您想在 Mathematica 中做一些棘手的事情时,通常会出现这种情况,模式匹配和规则替换可以帮助您。然而,在这种情况下,你必须做一些奇怪的事情,并且您必须使用
Replace
而不是ReplaceAll
(/.
运算符),以便您可以利用其可选的第三个参数给它一个级别规范。使用您提供的示例:看似无用的
规则实际上是一种记录方式在测试匹配和
With
结构体之间共享局部变量;在这里,您不对局部变量执行任何操作,而是以迂回方式强制对其求值——因为较少的迂回方式是行不通的!编辑添加:我认为您误解了
Level
的结果;该表达式的{2}
级别的两个表达式是2
和Plus[2, 2]
;您可以通过使用 level 的可选第三个参数来看到这一点,它的作用类似于Extract
的可选第三个参数:使用
{2}
级别规范,Replace
将尝试根据这两个表达式匹配并替换规则,并且它将对第二个表达式起作用。As is so often the case when you want to do something tricky in Mathematica, pattern matching and rule replacement come to the rescue. However, in this instance, you have to do something weird, and you have to use
Replace
instead ofReplaceAll
(the/.
operator) so you can take advantage of its optional third argument to give it a level specification. Using the example you offered:The useless-looking
rule is actually a documented way to share local variables between the test match and the body of the
With
structre; here you don't do anything with the local variable but force its evaluation in a roundabout way---because less roundabout ways won't work!EDIT to add: I think you're mis-interpreting the result of
Level
; the two expressions at level{2}
of this expression are2
andPlus[2, 2]
; you can see this by using the optional third argument to level, which does something similar to the optional third argument ofExtract
:With the
{2}
level spec,Replace
will try to match-and-replace the rule against these two expressions, and it will work on the second one.不涉及
Extract
的技术是将Hold
内的部分包装在内部Hold
中,然后释放外部Hold< /code>:
你可以朝这个方向玩各种游戏,但由于我无法说出你想做什么,所以有点难以具体。可能有用的方法是定义您自己的
Hold
,它会按照您想要的方式下降:请注意,一旦内部被包裹,这个就会接近外部
Hold
,因此例如Plus
的平坦度开始发挥作用:A technique which does not involve
Extract
is to wrap the parts insideHold
in innerHold
s, and then release the outerHold
:You can play various games in this direction, but since I can't tell what it is you want to do, it is a bit hard to be specific. Something that might be useful is to define your own
Hold
that descents however you want it to:Note that this one approaches the outer
Hold
s once the insides are wrapped, so that for instance the flatness ofPlus
kicks in:使用 答案,作者:Michael Pilat,可以写
HoldAndEvaluate
函数,该函数允许他计算表达式中所需的部分,而无需计算其位置(可以用“MyEvaluate”标记)。Using the idea about
ReplacePart
andExtract
functions from the answer by Michael Pilat, one can writeHoldAndEvaluate
function, which allows him to evaluate a desired part of the expression without the need to calculate its position (it can be marked with "MyEvaluate").