Hi Jan,

Thank you for reply. I see your point on *shift* and *throw*. I agree. This is a concrete example on your request, though it is not complete one, but I hope my use of *balls* shifted are always used only in the form of *call(ball)*. My main purpose of using *shift* is to hide *state* from programming on ZDD like *phrase* to hide string from programming on given a grammar, though this may be my superficial impression on *shift/reset*. Anyway it turned out very useful for the current purpose of mine. Overhead of *shift/reset* seems good as far as profile tells, though I am occupied only for first climbing high two walls of ZDD (counting paths and associative algebras).

```
% ?- zdd((X<< pow([a,b]), card(X, C), psa(X)))
%@
%@ zdd 3:
%@ []
%@ [b]
%@ [a]
%@ [a,b]
%@ X = 3,
%@ C = 4.
```

where, *pow* is for powerset, *card* is for cardinality, *psa* is for *printing* a zdd in state at *X* for debugging. This is a complete source listing of *card/2*, in which *shift* is used as a la phrase/1,2,3 in the typical usage of *shift* in my ZDD package. There is no other way of use.

```
card(X, Y):- shift(card(X, Y)).
%
card(X, Y, S):- setup_call_cleanup( open_memo(M),
card(X, Y, S, M),
close_memo(M)).
card(I, I, _, _):- I < 2, !.
card(I, C, S, M):- memo(I-C, M),
( nonvar(C) -> true
; cofact(I, t(_, L, R), S),
card(R, Cr, S, M),
card(L, Cl, S, M),
C is Cl + Cr
).
```

```
zdd(E):- context_module(M),
setup_call_cleanup(
open_state(S),
zdd(E, S, M),
close_state(S)).
%
zdd((A,B), S, M):-!, zdd(A, S, M), zdd(B, S, M).
zdd(X<<E, S, _):-!, zdd_eval(E, X, S).
zdd(M:G, S, _):-!, zdd(G, S, M).
zdd(0, _, _):-!.
zdd(true, _, _):-!.
zdd({G}, _, _):-!, call(G).
zdd((A;B), S, M):-!, (zdd(A, S, M); zdd(B, S, M)).
zdd((A->B), S, M):-!, (zdd(A, S, M)->zdd(B, S, M)).
zdd(Cont, S, M):- reset(M:Cont, Ball, Cont0),
( var(Ball) -> true
; call(Ball, S)
),
zdd(Cont0, S, M).
%
zdd_eval(X, X, _) :-integer(X), !. % for any x >= 0.
zdd_eval(L, Y, S) :-is_list(L), !, sort(L, L0),
list_to_path(L0, Y, S).
zdd_eval({X}, Y, S) :-!, comma_to_list(X, U, []), zdd_family(U, Y, S).
zdd_eval(dnf(A), X, S):-!, expand_boole_macro(A, A0),
boole_to_dnf(A0, X, S).
zdd_eval(cnf(A), X, S):-!, expand_boole_macro(A, A0),
boole_to_cnf(A0, X, S).
zdd_eval(X + Y, A1, S):-!, zdd_eval(X, A2, S),
zdd_eval(Y, A3, S),
zdd_join(A2, A3, A1, S).
zdd_eval(X * Y, A1, S):-!, zdd_eval(X, A2, S),
zdd_eval(Y, A3, S),
zdd_meet(A2, A3, A1, S).
zdd_eval(X - Y, A1, S):-!, zdd_eval(X, A2, S),
zdd_eval(Y, A3, S),
zdd_subtr(A2, A3, A1, S).
zdd_eval(\(X,Y), A, S):-!, zdd_eval(X-Y, A, S).
zdd_eval(merge(X, Y), A1, S):-!, zdd_eval(X, A2, S),
zdd_eval(Y, A3, S),
zdd_merge(A2, A3, A1, S).
zdd_eval(&(X, Y), A, S):-!, zdd_eval(merge(X, Y), A, S).
zdd_eval(prod(X, Y), A1, S):-!, zdd_eval(X, A2, S),
zdd_eval(Y, A3, S),
zdd_product(A2, A3, A1, S).
zdd_eval(**(X, Y), A, S):-!, zdd_eval(prod(X, Y), A, S).
zdd_eval(pow(X), A, S) :-!, zdd_power(X, A, S).
zdd_eval(power(X), A, S):-!, zdd_eval(pow(X), A, S).
zdd_eval(sets(X), A, S) :-!, zdd_eval(X, Y, S),
sets(Y, A, S).
zdd_eval(zdd(E), A, S) :-!, call(E, A, S).
zdd_eval(Other, A, S) :- call(Other, B), zdd_eval(B, A, S).
```

Kuniaki Mukai