我可以自动懒惰地评估Mathematica中的函数参数吗?

时间:2011-07-16 05:50:35

标签: wolfram-mathematica lazy-evaluation

在Mathematica,我想做的事情是:

f[Rational[a_, b_], Rational[c_, d_]] := {a+c, b+d}

但是如果我用以下形式的表达式来评估它,我会得到错误的结果:

In: f[Rational[50, 100], Rational[4, 10]]
Out: {3, 7}
(* Expected: 54 / 110 ->  27 / 55 *)

有什么方法可以强迫Mathematica立即停止简化表达式?我可以暂时保留我传入的内容,然后让有问题的函数只需调用ReleaseHold [..]就可以传入任何内容。

这个解决方案非常难看,我不想这样做。我知道Mathematica中的一些函数会自动保存传入的内容并因某种原因延迟评估它,我想在此处这样做。

简而言之:我如何强迫Mathematica懒惰地评估传递给函数的内容而无需手动持有它?

2 个答案:

答案 0 :(得分:5)

  

在标准评估程序中,依次评估函数的每个参数。通过设置HoldFirst,HoldRest和HoldAll属性可以防止这种情况。这些属性使Mathematica以未评估的形式“保留”特定的参数。

http://reference.wolfram.com/legacy/v5/TheMathematicaBook/PrinciplesOfMathematica/EvaluationOfExpressions/2.6.5.html

e.g。

文档说当你第一次在函数体中使用它们时,会自动评估任何auto-Held参数。但是,如果由于某种原因你想继续使用Hold表单中的参数(例如,如果你想对表达式的未评估形式进行模式匹配和重写),那么也许你可以重新{{1}它。

答案 1 :(得分:1)

使用提到的HoldAll属性ninjagecko,我能够制定解决方案。

实际上还有另一个问题,我无法立即看到。具体来说,我的功能不是我认为的模式匹配。

我认为我最初的问题只是Mathematica自动简化了我的表达式,我需要懒洋洋地评估传入的参数以确保正确的行为。

实际上,我忘记了在Mathematica中有多种表达表达式的方法。作为玩具示例,请考虑以下函数,该函数提取分数的分子和分母:

ExtractNumDem[Fraction[a_, b_]] := {a, b}
(* Already incorrect, ExtractNumDem[4 / 100] gives {1, 25} *)

只需添加HoldAll(或HoldFirst偶数)属性就会产生另一个问题:

SetAttributess[ExtractNumDem, HoldAll];
ExtractNumDem[4 / 100] (* Gives ExtractNumDem[4 / 100] *)

表达式4 / 100实际上正在评估Times[4, Power[100, -1]]。为了解决第二个问题,我必须为看起来像这样的分数添加一个定义:

ExtractNumDem[Times[a_, Power[b_, -1]] := {a, b}
ExtractNumDem[4/100] (* Now gives {4, 100} *)

我在原始答案中解决问题的解决方案采用了相同的原则。这里有一些代码可以实际看到我遇到的问题:

ClearAll[ExtractNumDem]

ExtractNumDem[Rational[a_, b_]] := {a, b}
ExtractNumDem[4 / 100]

SetAttributes[ExtractNumDem, HoldAll];
ExtractNumDem[4 / 100]

ExtractNumDem[Times[a_, Power[b_, -1]]] := {a, b}
ExtractNumDem[4/100]