虽然正常统一又名双边统一与内置 (=)/2 密切相关,但模式匹配又名一侧统一与内置 (==)/2 之间存在类似的关系。这些引导程序将起作用:
=(X,X) :- true.
==(X,X) => true.
如果我们查看 Quine 算法的代码,从这里获取,我们会发现很多 (==)/2 用途。模式匹配可以直接做的工作:
simp(A, A) :- var(A), !.
simp(A+B, B) :- A == 0, !.
simp(A+B, A) :- B == 0, !.
Etc..
所以我们试了一下,把所有的规则都转换成模式匹配。然后不再需要初始的 var/1 保护, (==)/2 也不再需要。但是我们观察到我们需要更多 (=)/2 来返回函数值:
simp(0+B, X) => X = B.
simp(A+0, X) => X = A.
Etc..
我们做了一个小基准测试并验证了来自 Principia 的 193 个命题逻辑测试用例。我们测试了正常的统一和模式匹配。我们还与尚未编译的模式匹配变体进行了比较,这是使用 subsumes/2 的扩展:
首先通过 subsumes/2 进行扩展,它不编译模式匹配:
/* Jekejeke Prolog 1.5.0 */
/* normal unification */
?- time((between(1,380,_), test, fail; true)).
% Up 996 ms, GC 6 ms, Threads 984 ms (Current 02/14/21 11:30:28)
Yes
/* pattern matching */
?- time((between(1,380,_), test, fail; true)).
% Up 3,525 ms, GC 24 ms, Threads 3,500 ms (Current 02/14/21 11:42:50)
Yes
现在 SWI-Prolog 的新编译模式匹配:
/* SWI-Prolog 8.3.19 */
/* normal unification */
?- time((between(1,380,_), test, fail; true)).
% 4,940,000 inferences, 0.547 CPU in 0.534 seconds (102% CPU, 9033143 Lips)
true.
/* pattern matching */
?- time((between(1,380,_), test, fail; true)).
% 4,940,000 inferences, 0.531 CPU in 0.531 seconds (100% CPU, 9298824 Lips)
true.
我原以为编译后的方法显示了一个tick 更多的bang而不是只保存正常统一的性能?但无论如何,这是一个好的开始。
开源:
1847 年的布尔方法,Prolog 风格
https://gist.github.com/jburse/713b6ad2b7e28de89fe51b98be3d0943#file-boole-pl
1847 年的布尔方法,皮卡特风格
https://gist.github.com/jburse/713b6ad2b7e28de89fe51b98be3d0943#file-boole2-pl
Picat 扩展
https://gist.github.com/jburse/713b6ad2b7e28de89fe51b98be3d0943#file-picat-pl
来自 Principia 的 193 个命题逻辑测试用例
https://gist.github.com/jburse/713b6ad2b7e28de89fe51b98be3d0943#file-principia-pl