Я думаю, что все забывают о побочных эффектах, которые возможны в тестовых функциях. Вот что, я думаю, происходит: как упомянули Mr.Wizard и другие, существует несколько способов, которыми шаблон может соответствовать, просто комбинаторно. Для каждой комбинации {x}
и {y}
сначала проверяется шаблон x
. Кстати, нет смысла определять функции нескольких аргументов (##
), поскольку, как объяснил @Simon, тестовая функция применяется отдельно к каждому элементу в последовательности. И это также объясняет, почему печатается только первый элемент (-1): как только первый несоответствующий элемент найден, сопоставление с образцом останавливается и продолжается для проверки следующей доступной комбинации.
Вот более наглядный пример:
In[20]:=
MatchQ[{-1,2,3,4,5},{_,x__?(Function[Print[#];Positive[#]])}]
During evaluation of In[20]:= 2
During evaluation of In[20]:= 3
During evaluation of In[20]:= 4
During evaluation of In[20]:= 5
Out[20]= True
Теперь он печатает все из них, поскольку функция применяется к ним один за другим, как и в этом случае.
Теперь к сути дела. Здесь я настроил тестовую функцию с побочным эффектом, которая решает передумать после того, как проверит самый первый элемент:
Module[{flag = False},
ClearAll[test3];
test3[x_] :=
With[{fl = flag},
If[! flag, flag = True];
Print[x];
fl
]
];
Первая комбинация (которая {-1},{2,3,4,5}
будет отклонена, так как функция сначала выдаст False
. Однако будет принята вторая ({-1,2},{3,4,5}
). И это именно то, что мы наблюдаем:
In[22]:=
MatchQ[{-1,2,3,4,5},{x__?test3,y__}]
During evaluation of In[22]:= -1
During evaluation of In[22]:= -1
During evaluation of In[22]:= 2
Out[22]= True
Печать остановилась, как только сопоставитель шаблонов обнаружил совпадение.
Теперь, отсюда, должно быть очевидно, что оптимизация, упомянутая в вопросе и некоторых других ответах, в общем случае невозможна, поскольку средство сопоставления с образцом не контролирует изменяемое состояние, возможно присутствующее в функциях тестирования.
Когда мы думаем о сопоставлении с образцом, мы обычно рассматриваем его как процесс, отдельный от оценки, что в значительной степени верно, так как сопоставление с образцом является встроенным компонентом системы, который после оценки шаблонов и выражений принимает и в значительной степени обходит основной цикл оценки. Однако есть заметные исключения, которые делают сопоставление с образцом более мощным за счет запутывания его с оценщиком. Они включают в себя использование Condition
и PatternTest
, поскольку эти два являются «точками входа» основного процесса оценки в иным образом изолированный от него процесс сопоставления с образцом. Как только шаблонное совпадение достигает одного из них, оно вызывает главного оценщика для условия, подлежащего проверке, и тогда все возможно. Что еще раз подводит меня к наблюдению, что средство сравнения шаблонов наиболее эффективно, когда тесты с использованием PatternTest
и Condition
отсутствуют, а шаблоны полностью синтаксические - в случае , в случае , он может оптимизироваться.