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]
Я упоминал о переупорядочении правил в нескольких местах в моей книге: здесь , здесь и здесь.В редких случаях, когда Mathematica переупорядочивает правила способом, который является неудовлетворительным, вы можете изменить порядок вручную путем прямых манипуляций с DownValues
(или другими ... значениями), например, такими как DownValues[f] = Reverse[DownValues[f]]
.Такие случаи случаются иногда, но довольно редко, и если они случаются, убедитесь, что есть веская причина сохранить существующий дизайн и перейти к ручному переупорядочению правил.