# Transparent shift/1 wanted

**URL:** <https://swi-prolog.discourse.group/t/transparent-shift-1-wanted/3058>\
**Category:** Predicate\
**Created:** [October 17, 2020, 8:51am UTC](https://swi-prolog.discourse.group/t/transparent-shift-1-wanted/3058 "2020-10-17T08:51:45Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![kuniaki.mukai](https://avatars.discourse-cdn.com/v4/letter/k/c67d28/32.png) [@kuniaki.mukai](https://swi-prolog.discourse.group/u/kuniaki.mukai)\
**Post date:** [October 17, 2020, 8:51am UTC](https://swi-prolog.discourse.group/t/transparent-shift-1-wanted/3058/1 "2020-10-17T08:51:45Z")

</div>

I have found the following two lines solves my trouble for  
“unknown procedure” error for “shifted” call.

:- meta\_predicate shift\_ala\_phrase(:).  
shift\_ala\_phrase(X):- shift(X).

Kuniaki Mukai

So far I use shift/1 of shift/reset in a way like the meta predicate phrase of DCG for hiding states like Haskel monad. However, restructuring my ZDD library, I noticed that shift/1 is not a meta\_predicate.

```prolog
    	?- predicate_property(shift(_), P).
	?- predicate_property(call(_), P). 

```

That is, the shift is not transparent at all. In my use of shift/reset, shifted “ball” Ball by shift(Ball) is always used in the form call(Ball, S) afterward for a state S given from reset. Non-transparency of shift for such use is inconvenient for restructuring codes so as to see many “unknown predicate” execution errors.  
Although this is an abuse of shift of mine, as a DCG user, it seems a reasonable usage. I would like to see a new meta predicate shift\_ala\_phrase/1 added to shift/reset related predicates in the future.

Kuniaki Mukai

---

<div class="post-metadata">

**Author:** ![jan](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/jan/32/4_2.png) [@jan](https://swi-prolog.discourse.group/u/jan)\
**Post date:** [October 17, 2020, 4:29pm UTC](https://swi-prolog.discourse.group/t/transparent-shift-1-wanted/3058/2 "2020-10-17T16:29:44Z")

</div>

I’m afraid I need a running example that indicates the problem. shift/1 as such has no reason to be aware of modules. Possibly the stack snapshot needs to preserve more information, but without a concrete example I can’t really tell.

---

<div class="post-metadata">

**Author:** ![kuniaki.mukai](https://avatars.discourse-cdn.com/v4/letter/k/c67d28/32.png) [@kuniaki.mukai](https://swi-prolog.discourse.group/u/kuniaki.mukai)\
**Post date:** [October 17, 2020, 5:11pm UTC](https://swi-prolog.discourse.group/t/transparent-shift-1-wanted/3058/3 "2020-10-17T17:11:32Z")

</div>

As I edited my help question, I have solved it for myself":

```prolog
:- meta_predicate shift_ala_phrase(:).
shift_ala_phrase(X):- shift(X).

```

Without reading doc on shift carefully, I thought shift/2 is a meta predicate. Is there some reason why shift/1 is not a meta predicate ?  
shift and phrase look similar.

Kuniaki Mukai

---

<div class="post-metadata">

**Author:** ![jan](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/jan/32/4_2.png) [@jan](https://swi-prolog.discourse.group/u/jan)\
**Post date:** [October 18, 2020, 7:24am UTC](https://swi-prolog.discourse.group/t/transparent-shift-1-wanted/3058/4 "2020-10-18T07:24:13Z")

</div>

> [@kuniaki.mukai](#):
>
> Is there some reason why [shift/1](https://www.swi-prolog.org/pldoc/doc_for?object=shift/1) is not a meta predicate ?

The _ball_ is basically unrelated to modules. I think the question is close to why throw/1 is not a meta-predicate. There can of course be reasons that you want to include the module into the _ball_. If so, your proposal makes sense. Just declaring shift/1 is a meta-predicate most likely breaks a lot of code for no good reason. I’d need a concrete example of the code to see whether what you are doing is how shift/reset are supposed to be used. But hey, many predicates find applications the developers have not anticipated 🙂

---

<div class="post-metadata">

**Author:** ![kuniaki.mukai](https://avatars.discourse-cdn.com/v4/letter/k/c67d28/32.png) [@kuniaki.mukai](https://swi-prolog.discourse.group/u/kuniaki.mukai)\
**Post date:** [October 18, 2020, 9:54am UTC](https://swi-prolog.discourse.group/t/transparent-shift-1-wanted/3058/5 "2020-10-18T09:54:34Z")

</div>

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).

```prolog
% ?- 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.

```prolog
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
	).

```

```prolog
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

---

<div class="post-metadata">

**Author:** ![jan](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/jan/32/4_2.png) [@jan](https://swi-prolog.discourse.group/u/jan)\
**Post date:** [October 18, 2020, 2:29pm UTC](https://swi-prolog.discourse.group/t/transparent-shift-1-wanted/3058/6 "2020-10-18T14:29:42Z")

</div>

> [@kuniaki.mukai](#):
>
> ```prolog
> zdd(Cont, S, M):- reset(M:Cont, Ball, Cont0),
> (	var(Ball) -> true
> ;	call(Ball, S)
> ),
> zdd(Cont0, S, M).
> 
> ```

Hmm. Seems all the shift/reset is doing is to give some call access to some variable that is only known higher up in the call tree, right? Seems you can also get there the classical way using program transformation or the tricky way discussed here recently by inspecting the stack, looking for the right zdd parent goal. That only requires a scan of the stacks rather than copying them.

---

<div class="post-metadata">

**Author:** ![kuniaki.mukai](https://avatars.discourse-cdn.com/v4/letter/k/c67d28/32.png) [@kuniaki.mukai](https://swi-prolog.discourse.group/u/kuniaki.mukai)\
**Post date:** [October 18, 2020, 3:00pm UTC](https://swi-prolog.discourse.group/t/transparent-shift-1-wanted/3058/7 "2020-10-18T15:00:00Z")

</div>

> > | [jan](https://swi-prolog.discourse.group/u/jan)  
> > October 18 |
> > 
> > - | - |
> 
> > ![](https://global.discourse-cdn.com/free1/uploads/swiprolog/original/2X/4/4c8398944078287cc4c5dcb87e9efd2586397af0.png)kuniaki.mukai:
> > 
> > ```prolog
> > zdd(Cont, S, M):- reset(M:Cont, Ball, Cont0),
> > (	var(Ball) -> true
> > ;	call(Ball, S)
> > ),
> > zdd(Cont0, S, M).
> > 
> > ```
> 
> Hmm. Seems all the shift/reset is doing is to give some call access to some variable that is only known higher up in the call tree, right?

Perhaps Yes. In fact before I knew shift/reset, I did it using global variables with b\_setval/b\_getval.

> Seems you can also get there the classical way using program transformation or the tricky way discussed here recently by inspecting the stack, looking for the right zdd parent goal. That only requires a scan of the stacks rather than copying them.

The stack is a kind of sacred place into which only selected priests are allowed to enter. At least for the time being, I should be satisfied with my current use of shift/reset.

Thank you for comments.

Kuniaki Mukai
