在最近问题&{34; my previous answer "的Prolog binary search tree test - unwanted parents' parent node comparison中,我建议混合使用prolog-coroutining的lazy_chain/2
...
:- use_module(library(clpfd)). lazy_chain(Zs, R_2) :- ( var(R_2) -> instantiation_error(R_2) ; clpfd:chain_relation(R_2) -> freeze(Zs, lazy_chain_aux(Zs,R_2)) ; otherwise -> domain_error(chain_relation, R_2) ). lazy_chain_aux([], _). lazy_chain_aux([Z0|Zs], R_2) :- freeze(Zs, lazy_chain_aux_(Zs,R_2,Z0)). lazy_chain_aux_([], _, _). lazy_chain_aux_([Z1|Zs], R_2, Z0) :- call(R_2, Z0, Z1), freeze(Zs, lazy_chain_aux_(Zs,R_2,Z1)).
...与dcg in_order//1
...
in_order(nil) --> []. in_order(node(X,L,R)) --> in_order(L), [X], in_order(R).
......就像这样:
?- lazy_chain(Zs, #<), phrase(in_order(node(1,nil,nil)), Zs). Zs = [1,23].
是否有一种轻松的方式来推动&#34; lazy_chain
进入phrase/3
,以便其范围仅限于in_order//1
所描述的序列部分?
现在,我明白了......
?- lazy_chain(Zs, #<), phrase(in_order(node(1,nil,nil)), Zs0,Zs). Zs0 = [1|Zs], freeze(Zs, lazy_chain_aux(Zs,#<)).
... {当然)在进一步实例化Zs
:
?- lazy_chain(Zs, #<), phrase(in_order(node(1,nil,nil)), Zs0,Zs), Zs = [3,2,1]. false.
我如何解决这个问题并将lazy_chain
约束到list-difference的部分?
答案 0 :(得分:2)
与此同时,我提出了以下黑客行为:
lazy_chain_upto(R_2, P_2, Xs0, Xs) :-
( var(R_2) -> instantiation_error(R_2)
; clpfd:chain_relation(R_2) -> when((nonvar(Xs0) ; ?=(Xs0,Xs)),
lazy_chain_upto_aux(Xs0,Xs,R_2)),
phrase(P_2, Xs0, Xs)
; otherwise -> domain_error(chain_relation, R_2)
).
lazy_chain_upto_aux(Xs0, Xs, _) :-
Xs0 == Xs,
!.
lazy_chain_upto_aux([], _, _).
lazy_chain_upto_aux([X|Xs0], Xs, R_2) :-
when((nonvar(Xs0) ; ?=(Xs0,Xs)), lazy_chain_upto_prev_aux(Xs0,Xs,R_2,X)).
lazy_chain_upto_prev_aux(Xs0, Xs, _, _) :-
Xs0 == Xs,
!.
lazy_chain_upto_prev_aux([], _, _, _).
lazy_chain_upto_prev_aux([B|Xs0], Xs, R_2, A) :-
call(R_2, A, B),
when((nonvar(Xs0) ; ?=(Xs0,Xs)), lazy_chain_upto_prev_aux(Xs0,Xs,R_2,B)).
基于此,我们可以像这样定义in_orderX//1
:
in_orderX(T) --> lazy_chain_upto(#<, in_order(T)).
问题中显示的示例查询...
?- phrase(in_orderX(node(1,nil,nil)), Zs0,Zs), Zs = [3,2,1].
Zs0 = [1,3,2,1], Zs = [3,2,1].
...现在检查好了,但仍然我想知道:值得吗?
答案 1 :(得分:0)
我没有看到混合corouting和DCG的任何问题。 DCG只是从DCG规则H --> B
到一些普通的Prolog规则H' :- B'
的翻译。任何约束发布都可以包含在{}/1
。
以下是Quines的示例:
% eval(+Term, +List, -Term, +Integer)
eval([quote,X], _, X) --> [].
eval([cons,X,Y], E, [A|B]) -->
step,
eval(X, E, A),
eval(Y, E, B).
eval([lambda,X,B], E, [closure,X,B,E]) --> [].
eval([X,Y], E, R) -->
step,
{neq(X, quote), sto(B)},
eval(X, E, [closure,Z,B,F]),
{sto(A)},
eval(Y, E, A),
eval(B, [Z-A|F], R).
eval(S, E, R) -->
{freeze(S, is_symbol(S)), freeze(E, lookup(S, E, R))}.
你可以为lazy_chain_upto//2
做同样的事情。作为一个开始你
可以继续定义lazy_chain_upto//2
的第一个子句
如下:
lazy_chain_upto(R_2, P_2) -->
( {var(R_2)} -> {instantiation_error(R_2)}
; {clpfd:chain_relation(R_2)} -> /* ?? */
; {otherwise} -> {domain_error(chain_relation, R_2)}
)
在/* ?? */
部分,您也可以从DCG-ifyed lazy_chain_upto_aux//1
谓词中获益。当然我假设DCG翻译理解( - &gt;)和(;)/ 2。
再见