具有一条规则的纯 Prolog 元解释器
Pure Prolog Meta-Interpreter with one Rule
我想知道是否有一个纯 Prolog 元解释器
只有一个规则。通常的 Prolog 香草元解释器有两个
规则。内容如下:
solve(true).
solve((A, B)) :- solve(A), solve(B). /* rule 1 */
solve(H) :- program(H, B), solve(B). /* rule 2 */
这个 Prolog 香草元解释器使用两个规则 /* rule 1 */
和 /* rule 2 */
。剩下的就是事实。该计划
被执行由程序事实表示。这是一个示例程序:
program(append([], X, X), true).
program(append([X|Y], Z, [X|T]), append(Y, Z, T)).
program(nrev([], []), true).
program(nrev([H|T], R), (nrev(T, S), append(S, [H], R))).
还有一个示例查询:
?- solve(nrev([1,2,3], X)).
X = [3, 2, 1] .
有没有办法将程序以不同的方式表示为事实,并且
然后编写一个不同的元解释器,它只使用事实
除了一条规则而不是两条规则?会的东西
适用于所有纯 Prolog 程序,而不仅仅是 nrev 示例?
如果允许 ;/2
,那么这似乎可行:
solve(true).
solve(H) :- ((X, Y) = H, solve(X), solve(Y)); (program(H :- B), solve(B)).
program(append([], X, X) :- true).
program(append([X|Y], Z, [X|T]) :- append(Y, Z, T)).
program(nrev([], []) :- true).
program(nrev([H|T], R) :- (nrev(T, S), append(S, [H], R))).
测试:
?- solve(nrev([1,2,3], X)).
X = [3, 2, 1] ;
false.
这是一个想法,使用列表来保存剩余的计算:
solve([]).
solve([X|Xs]) :- program(X, Ys, Xs), solve(Ys).
program(true, Xs, Xs).
program(append([],X,X), Xs, Xs).
program(append([X|Y], Z, [X|T]), [append(Y,Z,T)|Xs], Xs).
program(nrev([],[]), Xs, Xs).
program(nrev([H|T],R), [nrev(T,S),append(S,[H],R)|Xs], Xs).
使用测试调用(需要将调用包装在列表中)。
?- solve([nrev([1,2,3],X)]).
X = [3,2,1] ? ;
no
可以说,可以将 program/3 事实表示为 DCG,以提高可读性(但这样它可能不再被视为“事实”)。
这是另一种方法,称为连续二值化。
它来自 Paul Tarau(2021 年)的逻辑转换器论文 here。
solve(true).
solve(X) :- program(X, Y), solve(Y).
program(append([],X,X,C), C).
program(append([X|Y],Z,[X|T],C), append(Y,Z,T,C)).
program(nrev([],[],C), C).
program(nrev([H|T],R,C), nrev(T,S,append(S,[H],R,C))).
一点完整性检查表明它有效:
?- solve(nrev([1,2,3], X, true)).
X = [3, 2, 1] ;
No
我想知道是否有一个纯 Prolog 元解释器 只有一个规则。通常的 Prolog 香草元解释器有两个 规则。内容如下:
solve(true).
solve((A, B)) :- solve(A), solve(B). /* rule 1 */
solve(H) :- program(H, B), solve(B). /* rule 2 */
这个 Prolog 香草元解释器使用两个规则 /* rule 1 */
和 /* rule 2 */
。剩下的就是事实。该计划
被执行由程序事实表示。这是一个示例程序:
program(append([], X, X), true).
program(append([X|Y], Z, [X|T]), append(Y, Z, T)).
program(nrev([], []), true).
program(nrev([H|T], R), (nrev(T, S), append(S, [H], R))).
还有一个示例查询:
?- solve(nrev([1,2,3], X)).
X = [3, 2, 1] .
有没有办法将程序以不同的方式表示为事实,并且 然后编写一个不同的元解释器,它只使用事实 除了一条规则而不是两条规则?会的东西 适用于所有纯 Prolog 程序,而不仅仅是 nrev 示例?
如果允许 ;/2
,那么这似乎可行:
solve(true).
solve(H) :- ((X, Y) = H, solve(X), solve(Y)); (program(H :- B), solve(B)).
program(append([], X, X) :- true).
program(append([X|Y], Z, [X|T]) :- append(Y, Z, T)).
program(nrev([], []) :- true).
program(nrev([H|T], R) :- (nrev(T, S), append(S, [H], R))).
测试:
?- solve(nrev([1,2,3], X)).
X = [3, 2, 1] ;
false.
这是一个想法,使用列表来保存剩余的计算:
solve([]).
solve([X|Xs]) :- program(X, Ys, Xs), solve(Ys).
program(true, Xs, Xs).
program(append([],X,X), Xs, Xs).
program(append([X|Y], Z, [X|T]), [append(Y,Z,T)|Xs], Xs).
program(nrev([],[]), Xs, Xs).
program(nrev([H|T],R), [nrev(T,S),append(S,[H],R)|Xs], Xs).
使用测试调用(需要将调用包装在列表中)。
?- solve([nrev([1,2,3],X)]).
X = [3,2,1] ? ;
no
可以说,可以将 program/3 事实表示为 DCG,以提高可读性(但这样它可能不再被视为“事实”)。
这是另一种方法,称为连续二值化。
它来自 Paul Tarau(2021 年)的逻辑转换器论文 here。
solve(true).
solve(X) :- program(X, Y), solve(Y).
program(append([],X,X,C), C).
program(append([X|Y],Z,[X|T],C), append(Y,Z,T,C)).
program(nrev([],[],C), C).
program(nrev([H|T],R,C), nrev(T,S,append(S,[H],R,C))).
一点完整性检查表明它有效:
?- solve(nrev([1,2,3], X, true)).
X = [3, 2, 1] ;
No