# Delimited continuations and forall

**URL:** <https://swi-prolog.discourse.group/t/delimited-continuations-and-forall/2658>\
**Category:** Help!\
**Created:** [July 19, 2020, 10:04pm UTC](https://swi-prolog.discourse.group/t/delimited-continuations-and-forall/2658 "2020-07-19T22:04:22Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![esad](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/esad/32/884_2.png) [@esad](https://swi-prolog.discourse.group/u/esad)\
**Post date:** [July 19, 2020, 10:04pm UTC](https://swi-prolog.discourse.group/t/delimited-continuations-and-forall/2658/1 "2020-07-19T22:04:22Z")

</div>

I’m bit surprised by the behaviour of delimited continuations when used together with `forall/2`.

Let’s start with a simple example which doesn’t use forall:

```prolog
shift_all([]):-!.
shift_all([X|Xs]):-shift(X), shift_all(Xs).

```

Querying `reset(shift_all([1,2,3]), X, Cont), reset(Cont, X2, Cont2)` returns X=1, X2=2 as expected.

Now when I try:

`reset(forall(member(M, [1,2,3]),shift(M)), X, Cont), reset(Cont, X2, Cont2)` I get:

```prolog
ERROR: Type error: `callable' expected, found `0' (an integer)
ERROR: In:
ERROR: [11] reset(user:0,_7526,_7528)

```

Can someone help explain what’s going on?

Is this because forall uses backtracking to drive the Generator and the first continuation “loses” knowledge of choice points, that is, it doesn’t backtrack to find next solution?

---

<div class="post-metadata">

**Author:** ![esad](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/esad/32/884_2.png) [@esad](https://swi-prolog.discourse.group/u/esad)\
**Post date:** [July 19, 2020, 10:36pm UTC](https://swi-prolog.discourse.group/t/delimited-continuations-and-forall/2658/2 "2020-07-19T22:36:18Z")

</div>

I’ve read the original paper at [https://www.swi-prolog.org/download/publications/iclp2013.pdf](https://www.swi-prolog.org/download/publications/iclp2013.pdf) and there’s even a small example with backtracking.

The problem is that, contrary to what I assumed, choice points are not “converted” into continuations but are propagated to wherever `reset` was called.

---

<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:** [July 20, 2020, 7:03am UTC](https://swi-prolog.discourse.group/t/delimited-continuations-and-forall/2658/3 "2020-07-20T07:03:00Z")

</div>

Yes. Delimited continuations do not play with commit, forall/2 is implemented using `\+/1`, which commits.

---

<div class="post-metadata">

**Author:** ![peter.ludemann](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/peter.ludemann/32/48_2.png) [@peter.ludemann](https://swi-prolog.discourse.group/u/peter.ludemann)\
**Post date:** [July 20, 2020, 7:37pm UTC](https://swi-prolog.discourse.group/t/delimited-continuations-and-forall/2658/4 "2020-07-20T19:37:46Z")

</div>

> [@jan](#):
>
> Delimited continuations do not play with commit

What do you mean by “commit”? Is this simply removing the choicepoint (that is, some kind of “cut”)?

forall/2 is actually a double negation:

```prolog
forall(Cond, Action) :-
    \+ (Cond, \+ Action).

```

PS:

> [@esad](#):
>
> `shift_all([]):-!.`

The cut probably isn’t needed. But that doesn’t change the error you get.

---

<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:** [July 22, 2020, 8:28am UTC](https://swi-prolog.discourse.group/t/delimited-continuations-and-forall/2658/5 "2020-07-22T08:28:31Z")

</div>

> [@peter.ludemann](#):
>
> What do you mean by “commit”? Is this simply removing the choicepoint (that is, some kind of “cut”)?

The usual idea of continuations is that you can abort (using shift/1) any computation and make it continue using call/1, just as if nothing happened. That is not always the case for Prolog’s continuations. The case that typically goes wrong is where you shift before a commit (!/0 or -\>) Let us consider this

```
 p, shift(Ball), q -> r ; s

```

Running this, the ;/2 choicepoint was created before the shift and thus remains part of the computation. If we resume after the shift, the link between the commit implied by → and the choice point of the ;/2 is lost and the → thus no longer has any effect. That is the original work. SWI-Prolog’s implementation can in some cases deal with the commit if the continuation is immediately restarted. Use cases such as tabling store the continuation for later reused though. In this case it doesn’t matter as tabling has the same limitations when dealing with commits.

Thus, shift only captures the current forward continuation, **not** the choice points.
