When mixing Prolog coroutining (freeze / 2, when / 2) and DCG

In my previous answer to the recent question “ Prolog Binary Search Tree Test - Parent Parent Source Node ” I suggested mixing lazy_chain/2, which uses prolog-coroutining ...

<Preview>: 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)); otherwisedomain_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)).

... along with in_order//1 ...

in_order (nil) -> [].
in_order (node ​​(X, L, R)) -> in_order (L), [X], in_order (R).

... like this:

<Preview>? - lazy_chain (Zs, # <),   phrase (in_order (node ​​(1, zero, zero)), Zs). Zs = [1.23].

Is there an easy way to "push" lazy_chainin phrase/3that its scope was limited to part of the sequence described in_order//1?

Right now, I get ...

<Preview>? - lazy_chain (Zs, # <),   phrase (in_order (node ​​(1, nil, nil)), Zs0, Zs). Zs0 = [1 | Zs], freeze (Zs, lazy_chain_aux (Zs, # <)).

... which (of course) may fail upon further creation Zs:

? - lazy_chain (Zs, # <),
   phrase (in_order (node ​​(1, nil, nil)), Zs0, Zs),
   Zs = [3,2,1].
to false .

How can I get around this and limit it to lazy_chainpart of ?

+4
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].

... , , : ?

+2

DCG. DCG - DCG H --> B, 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)}
   )

/* ?? */ DCT-ifyed lazy_chain_upto_aux//1. , , DCG (- > ) (;)/2.

Bye

0

Source: https://habr.com/ru/post/1624405/


All Articles