我想知道如果给出多个替换规则,mma如何确定在发生碰撞时首先应用哪个。一个例子是:
x^3 + x^2*s + x^3*s^2 + s x /. {x -> 0, x^_?OddQ -> 2}
感谢。
答案 0 :(得分:12)
Mathematica有一种机制,能够在简单的情况下确定规则的相对一般性,例如,它理解___
(BlankNullSequence)比__
(BlankSequence)更通用。因此,当它可以时,它会根据它重新排序全局定义。重要的是要意识到这种分析必然主要是语法。因此,虽然PatternTest (?)
和Condition (/;)
有一些简单的内置谓词如EvenQ
有时可以进行分析,但将它们与用户定义的谓词一起使用必然会使得这样的重新排序无法进行类似定义规则,以便Mathematica将按照输入的顺序保留这些规则。这是因为,PatternTest
和Condition
强制模式匹配器调用评估器来确定匹配的事实,这使得无法在定义 - 时间回答规则的相对一般性问题。即使对于纯粹的句法规则,也不总是可以确定它们的相对普遍性。因此,当无法做到这一点,或者Mathematica无法做到这一点时,它会按照输入的顺序保留规则。
这一切都是关于由Set
或SetDelayed
或其他任务运营商创建的全局规则。对于本地规则,例如在您的示例中,没有任何重新排序,它们按照它们在规则列表中的顺序应用。应用于给定(子)表达式的第一个规则之外的规则列表中的所有规则将针对该子表达式被忽略,并且该特定规则应用程序进程 - (子)表达式将根据第一个匹配规则进行重写,并且然后规则应用程序进程继续其他子表达式。即使重写(子)表达式的新形式与规则列表中的某些规则匹配,它们也不会应用于此规则应用程序进程中。换句话说,对于单个规则应用程序进程,对于任何特定(子)表达式,不应用任何规则或仅应用一个规则。但这里也有一些细微之处。例如,ReplaceAll (/.)
将规则从较大的表达式应用于子表达式,而具有显式级别规范的Replace
则以相反的方式执行。在这种情况下,这可能很重要:
In[1]:= h[f[x, y]] /. {h[x_f] :> a, f[args__] :> b}
Out[0]= a
In[2]:= Replace[h[f[x, y]], {h[x_f] :> a, f[args__] :> b}, {0, Infinity}]
Out[2]= h[b]
我在书中的几个地方提到了规则重新排序:here,here和here。在极少数情况下,当Mathematica以不满意的方式重新排序规则时,您可以通过使用DownValues
(或其他...值)直接操作来手动更改顺序,例如DownValues[f] = Reverse[DownValues[f]]
。这种情况有时会发生,但很少发生,如果发生这种情况,请确保有充分理由保留现有设计并进行手动规则重新排序。