在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懒惰地评估传递给函数的内容而无需手动持有它?
答案 0 :(得分:5)
在标准评估程序中,依次评估函数的每个参数。通过设置HoldFirst,HoldRest和HoldAll属性可以防止这种情况。这些属性使Mathematica以未评估的形式“保留”特定的参数。
e.g。
SetAttributes[yourFunction, HoldFirst]
文档说当你第一次在函数体中使用它们时,会自动评估任何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]