【发布时间】:2011-12-13 04:23:23
【问题描述】:
在准备对An unexpected behavior of PatternTest in Mathematica 的回复时,我遇到了我自己的意外Mathematica 行为。
请考虑:
test = (Print[##]; False) &;
MatchQ[{1, 2, 3, 4, 5}, {x__?test, y__}]
在计算 In[1]:= 1 期间 在评估 In[1]:= 1 在评估 In[1]:= 1 在评估 In[1]:= 1
错误
因为,正如西蒙对文档的引用简明扼要地指出:
以
__?test之类的形式,序列中的每个元素都与__匹配 应用测试时必须产生True。
我想知道为什么 Mathematica 会分别测试列表的第一个元素四次。当然有四种方法可以构成基本模式{x__, y__},如果这是一个Condition 测试,那么构成序列x 的所有元素都需要进行测试,但我认为这不是案例在这里。
如果列表的第一个元素失败PatternTest 那么给定的模式不能匹配,逻辑是否不成立?
如果它成立,为什么 Mathematica 不做这个简单的优化?
从 yoda 的回答中借用一个例子,这里是另一个似乎是过度评估的例子:
In[1]:= test2 = (Print@##; Positive@##) &;
MatchQ[{1, 2, 3, 4, -5}, {x__?test2, y__?Negative}]
During evaluation of In[1]:= 1
During evaluation of In[1]:= 1
During evaluation of In[1]:= 2
During evaluation of In[1]:= 1
During evaluation of In[1]:= 2
During evaluation of In[1]:= 3
During evaluation of In[1]:= 1
During evaluation of In[1]:= 2
During evaluation of In[1]:= 3
During evaluation of In[1]:= 4
Out[2]= True
我承认我以前从未探索过模式匹配的这一方面,我对这看似低效的做法感到不安。这真的像看起来那么糟糕,还是发生了某种自动缓存? Print 似乎对此表示反对。
有没有更有效的基于模式的方法来写这个?
正确的模式匹配行为是否需要这种冗余级别,为什么?
我仓促做出了错误的断言,但我留下了它,因为下面的好答案解决了这个问题。请在以后的答案中忽略它。
很容易证明在其他方面也进行了类似的优化 案例:
MatchQ[{-1, 2, 3, 4, 5}, {__?Positive, y__?test}](什么都不打印。)
错误这里 Mathematica 正确地甚至从未测试任何元素
y。
【问题讨论】:
标签: wolfram-mathematica pattern-matching