我编写了一个名为term_ctx_subterm / 3的谓词,它是术语,该术语的单孔上下文和填补空洞的子项之间的关系。在大多数情况下,谓词按我的意愿运作。请参阅下面的代码和使用示例。但是,我使用了两个子句来定义谓词,其中一个用于两种模式。在第一种模式中,该术语是一个化合物,它被解构为单孔上下文和相应的子项。在第二种模式中,给出单孔上下文,并使用子项来重建该项来填充孔。
我一直在尝试使用when / 2将term_ctx_subterm写成一个子句谓词,我认为我很接近但是a)它非常丑陋b)它不能正常工作。如何使用coroutining谓词使用单个子句实现term_ctx_subterm?
首先是版本1,有两个子句:
%! term_ctx_subterm(+Term, ?CtxHole, ?SubTerm) is nondet
%! term_ctx_subterm(?Term, +CtxHole, ?SubTerm) is det
%
% True when =Term= is equal to =CtxHole= if the hole is equal to
% SubTerm. =CtxHole= is a pair =Ctx-Hole= where =Ctx= is a term
% containing variable =Hole=.
%
term_ctx_subterm(Term, Ctx-Hole, SubTerm) :-
nonvar(Term),
!,
Term =.. [F|Args],
append(Left, [R|Right], Args),
append(Left, [R1|Right], CtxArgs),
Ctx =.. [F|CtxArgs],
(SubTerm = R,
Hole = R1
;
term_ctx_subterm(R, Ctx1-Hole, SubTerm),
R1 = Ctx1
),
Ctx =.. [F|CtxArgs].
term_ctx_subterm(Term, Ctx-Hole, SubTerm) :-
nonvar(Ctx),
!,
Term = Ctx,
Hole = SubTerm.
test1 :-
term_ctx_subterm(a(b, c(d)), Ctx-Hole, SubTerm).
% ?- term_ctx_subterm(a(b, c(d)), Ctx-Hole, SubTerm),
% Ctx = a(Hole, c(d)),
% SubTerm = b ;
% Ctx = a(b, Hole),
% SubTerm = c(d) ;
% Ctx = a(b, c(Hole)),
% SubTerm = d ;
% false
test2 :-
term_ctx_subterm(Term, a(b, c(Hole))-Hole, 'HERE').
% ?- term_ctx_subterm(Term, a(b, c(Hole))-Hole, 'HERE').
% Term = a(b, c('HERE')),
% Hole = 'HERE'.
test3 :- % should probably throw an instantiation error here
term_ctx_subterm(A, B, C).
% ?- term_ctx_subterm(A, B, C).
% false
%
在这个版本中,我尝试使用/ 2:
term_ctx_subterm_v2(Term, Ctx-Hole, SubTerm) :-
when((nonvar(Term); nonvar(F), ?=(Args, CtxArgs)),
(Term =.. [F|Args])),
when((nonvar(Ctx); nonvar(F), ?=(Args, CtxArgs)),
(Ctx =.. [F|CtxArgs])),
when((nonvar(Left);nonvar(Args)),
append(Left, [R|Right], Args)
),
when((nonvar(Left);nonvar(CtxArgs)),
append(Left, [R1|Right], CtxArgs)
),
(SubTerm = R,
Hole = R1
;
term_ctx_subterm_v2(R, Ctx1-Hole, SubTerm),
R1 = Ctx1
),
Ctx =.. [F|CtxArgs].
但以下情况不起作用:
[debug] ?- term_ctx_subterm_v2(Term, a(X)-X, 1).
when((nonvar(Term);nonvar(a), ?=([1], [X])), Term=..[a, 1]) ;
ERROR: Arguments are not sufficiently instantiated
ERROR: In:
ERROR: [9] _7658=..[_7664|_7666]
ERROR: [8] term_ctx_subterm_v2(_7690,_7698-_7700,1) at /Users/edechter/Dropbox/Projects/scratch/term_ctx_subterm.pl:52
ERROR: [7] term_ctx_subterm_v2(_7724,... - _7734,1) at /Users/edechter/Dropbox/Projects/scratch/term_ctx_subterm.pl:49
Exception: (9) _6952{when = ...}=..[_6840{when = ...}|_7228{when = ...}] ? ;
虽然它在第一个版本中运行良好:
[debug] ?- term_ctx_subterm(Term, a(X)-X, 1).
Term = a(1),
X = 1.