问题描述
我试过这个原版解释器:
solve(true) :- !,true.
solve(X is E) :- !,X is E.
solve((A,B)) :- !,solve(A),solve(B).
solve(H) :- clause(H,B),solve(B).
我们可以用它来元解释一些代码吗?我试过这个代码,
需要 SWI-Prolog 8.3.19,正常运行:
sumlist([X|Y],R) => sumlist(Y,H),R is X+H.
sumlist([],R) => R is 0.
?- sumlist([1,2,3],X).
X = 6.
?- sumlist(X,Y).
ERROR: No rule matches sumlist(_21604,_21606)
但是元解释出错了。原因是条款/2
不知道使用单边统一的规则:
?- clause(sumlist(A,C).
A = [_22728|_22730],C = (sumlist(_22730,_22736),B is _22728+_22736) ;
A = [],C = (B is 0).
?- solve(sumlist([1,X)).
X = 6.
?- solve(sumlist(X,Y)).
SWI-Prolog wurde unerwartet beendet.
元解释器和单边统一有解决方案吗?
解决方法
摆脱困境并留在 ISO 核心标准内的一种方法是将单面统一转换为 nonvar/1、(=)/2 和 (==)/2 的组合,如下所示:
?- clause(sumlist(X,Y),Z),write((sumlist(X,Y):-Z)),nl,fail; true.
sumlist(_A,_B) :- nonvar(_A),_A = [_C|_D],sumlist(_D,_E),_B is _C+_E
sumlist(_A,_A = [],_B is 0
当然,我们还需要将内置的 nonvar/1、(=)/2 和 (==)/2 添加到元解释器中:
solve(true) :- !.
solve(X is E) :- !,X is E.
solve(nonvar(X)) :- !,nonvar(X).
solve(X == Y) :- !,X == Y.
solve(X = Y) :- !,X = Y.
solve((A,B)) :- !,solve(A),solve(B).
solve(H) :- clause(H,B),solve(B).
元解释 sumlist/2 现在工作正常:
?- solve(sumlist([1,2,3],X)).
X = 6
?- solve(sumlist(X,Y)).
No
但是翻译者可能会挑战 Prolog 系统关于子句索引的问题。它将函子从头部移到身体中。因此,Prolog 系统需要一些由 YAP 开创并在 Jekejeke Prolog 中发现的身体前部索引。
开源:
另一种模式匹配器
https://gist.github.com/jburse/a3517410a28b759ef44f72584f89aaf8#file-picat3-pl
普通解释器,扩展解决方案
https://gist.github.com/jburse/a3517410a28b759ef44f72584f89aaf8#file-vanilla4-pl