# Distinguish undefined from true or false

**URL:** <https://swi-prolog.discourse.group/t/distinguish-undefined-from-true-or-false/3253>\
**Category:** General\
**Created:** [November 11, 2020, 8:43pm UTC](https://swi-prolog.discourse.group/t/distinguish-undefined-from-true-or-false/3253 "2020-11-11T20:43:12Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![swi](https://avatars.discourse-cdn.com/v4/letter/s/51bf81/32.png) [@swi](https://swi-prolog.discourse.group/u/swi)\
**Post date:** [November 11, 2020, 8:43pm UTC](https://swi-prolog.discourse.group/t/distinguish-undefined-from-true-or-false/3253/1 "2020-11-11T20:43:12Z")

</div>

How to determine if a predicate is undefined under [WFS](https://www.swi-prolog.org/pldoc/man?section=WFS)?

With this program:

```prolog
a :- undefined.

```

If we run

```prolog
11 ?- call_delays(a,R).
R = system:undefined,
undefined.

```

So we see that R gets instantiated with `system:undefined` if the predicate is undefined.

But the following doesn’t work, because the conjunction of undefined and true results in undefined.

```prolog
a :- undefined.

is_undefined(Pred) :-
   call_delays(Pred,R), 
   R == system:undefined
    -> true
   ; false.

```

```prolog
12 ?- is_undefined(a).
undefined.

```

How then could we write is\_undefined/1?

EDIT: Above I used -\>, but I would like a version that doesn’t cut the search tree (like \*-\>), but one thing at a time.

---

<div class="post-metadata">

**Author:** ![swi](https://avatars.discourse-cdn.com/v4/letter/s/51bf81/32.png) [@swi](https://swi-prolog.discourse.group/u/swi)\
**Post date:** [November 11, 2020, 8:48pm UTC](https://swi-prolog.discourse.group/t/distinguish-undefined-from-true-or-false/3253/3 "2020-11-11T20:48:35Z")

</div>

> [@EricGT](#):
>
> Just a quick glance, did not even test this, but should that not be
> 
> `R == system:undefined`

Yes, I had it like that in the code, but pasted the wrong version. Fixed in the post (results are the same).

---

<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:** [November 12, 2020, 8:26am UTC](https://swi-prolog.discourse.group/t/distinguish-undefined-from-true-or-false/3253/4 "2020-11-12T08:26:44Z")

</div>

First of all, a _predicate_ is not undefined (disregarding the old discussion about what is a predicate). Only _answers_ (solutions) can be undefined. A query can thus return both normal and undefined answers. See [https://swish.swi-prolog.org/p/russels%20paradox.swinb](https://swish.swi-prolog.org/p/russels%20paradox.swinb)

Next, `system:undefined` is only one version of undefined. To decide that an answer is undefined use `Delays \== true`. Typically, programs will not return `undefined` unless they call `undefined` explicitly.

Hope this helps …

---

<div class="post-metadata">

**Author:** ![swi](https://avatars.discourse-cdn.com/v4/letter/s/51bf81/32.png) [@swi](https://swi-prolog.discourse.group/u/swi)\
**Post date:** [November 12, 2020, 12:27pm UTC](https://swi-prolog.discourse.group/t/distinguish-undefined-from-true-or-false/3253/5 "2020-11-12T12:27:48Z")

</div>

> [@jan](#):
>
> First of all, a _predicate_ is not undefined (disregarding the old discussion about what is a predicate). Only _answers_ (solutions) can be undefined.

This kind of clarification really helps, thanks!

> [@jan](#):
>
> Next, `system:undefined` is only one version of undefined. To decide that an answer is undefined use `Delays \== true` . Typically, programs will not return `undefined` unless they call `undefined` explicitly.

That still doesn’t work:

```prolog
a :- undefined.

is_undefined(Pred) :-
   call_delays(Pred,R),
   R \== true
   -> true
   ; false.

```

```prolog
1 ?- is_undefined(a).
undefined.

```

What I would like to have is the following:

```prolog
1 ?- is_undefined(a).
true.

```

---

<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:** [November 12, 2020, 1:53pm UTC](https://swi-prolog.discourse.group/t/distinguish-undefined-from-true-or-false/3253/6 "2020-11-12T13:53:22Z")

</div>

Your definition is the same as below. Why cut the choice points?

```prolog
is_undefined(Pred) :-
   call_delays(Pred,R),
   R \== true,
   !.

```

I think there are only two ways to get rid of the pending delay list which carries the _undefined_ status:

- Backtrack, i.e., use findall/3 or double negation if you only want a semidet answer.
- Fill the table (by calling `forall(Pred,true)`) and use get\_returns\_and\_tvs/3 (after get\_calls/3) to read the table answers and their true/undefined status.

---

<div class="post-metadata">

**Author:** ![swi](https://avatars.discourse-cdn.com/v4/letter/s/51bf81/32.png) [@swi](https://swi-prolog.discourse.group/u/swi)\
**Post date:** [November 12, 2020, 3:48pm UTC](https://swi-prolog.discourse.group/t/distinguish-undefined-from-true-or-false/3253/7 "2020-11-12T15:48:39Z")

</div>

> [@jan](#):
>
> Why cut the choice points?

I’ve been coding in a procedural language for a couple of weeks (rust) and it has messed up my prolog mind, I hope I can get it back 😁

> [@jan](#):
>
> I think there are only two ways to get rid of the pending delay list which carries the _undefined_ status:
> 
> - Backtrack, i.e., use [findall/3](https://www.swi-prolog.org/pldoc/doc_for?object=findall/3) or double negation if you only want a semidet answer.
> - Fill the table (by calling `forall(Pred,true)` ) and use [get\_returns\_and\_tvs/3](https://www.swi-prolog.org/pldoc/doc_for?object=get_returns_and_tvs/3) (after [get\_calls/3](https://www.swi-prolog.org/pldoc/doc_for?object=get_calls/3)) to read the table answers and their true/undefined status.

I am at a loss here, need some help. Should not the following return some answers?

```prolog
a :- undefined.

```

```prolog
18 ?- forall(a,true), get_calls(a,T,R).
false. % Should I not get some answers here?

```

---

<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:** [November 12, 2020, 4:23pm UTC](https://swi-prolog.discourse.group/t/distinguish-undefined-from-true-or-false/3253/8 "2020-11-12T16:23:25Z")

</div>

> [@swi](#):
>
> I hope I can get it back

Success 🙂

> [@swi](#):
>
> `get_calls(a,T,R).`

get\_calls/2 returns tables for instances of its first argument. As `a/0` is not tabled no such tables exist. If you want this to work on an arbitrary goal, findall/3 is your only hope.

I have no clue what you are really trying to achieve. A more high level view on your problem might give more accurate answers. Considering that XSB (from which all this is derived) does (AFAIK) not have what you want and these people have decades of experience using this in the real world, my suspicion is that you want something that you should not have wanted in the first place.

---

<div class="post-metadata">

**Author:** ![swi](https://avatars.discourse-cdn.com/v4/letter/s/51bf81/32.png) [@swi](https://swi-prolog.discourse.group/u/swi)\
**Post date:** [November 12, 2020, 4:32pm UTC](https://swi-prolog.discourse.group/t/distinguish-undefined-from-true-or-false/3253/9 "2020-11-12T16:32:52Z")

</div>

> [@jan](#):
>
> get\_calls/2 returns tables for instances of its first argument. As `a/0` is not tabled no such tables exist.

Ahh…I see why now.

> [@jan](#):
>
> my suspicion is that you want something that you should not have wanted in the first place.

I was just trying to learn WFS; in looking at the barber problem with `findall(X,shaves(barber,X),Xs)`; I noticed that the result was `[barber,mayor]`; so the information about the `barber` answer being conditional was lost.

I surmised that there would be problems with findall, but that set me on a quest to see if I could reason when the answer of a predicate would be conditional (undefined), and that is why I tried to code `is_undefined(...)`.

What do people do when they have a nondet WFS predicate and they want to get all the backtracking answers that are undefined? (or all true for that matter?) I can certainly see many real world problems when you would want to reason differently (programmatically) if the answer was conditional (e.g. the toplevel, reacts differently if the answer is conditional).

EDIT: I am thinking about WFS principally as a three-valued logic, but perhaps this is the wrong way to think about it.

---

<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:** [November 12, 2020, 4:58pm UTC](https://swi-prolog.discourse.group/t/distinguish-undefined-from-true-or-false/3253/10 "2020-11-12T16:58:22Z")

</div>

Don’t ask me 🙂 I implemented this stuff with the help of Theresa Swift and David S. Warren, but so far I did little with it except for playing …

Anyway, to get the true answers I’d guess this will do:

```
?- findall(X,call_delays(shaves(barber,X),true), Xs).

```

And to get the undefined ones

```
?- findall(X,(call_delays(shaves(barber,X),Delays), Delays \== true), Xs).

```

In most cases you probably better refrain from using all solution predicates in the context of tabling. Quite often it is not a particularly good idea to represent solutions to a predicate as a list anyway. Just leave the set implicit, possibly except for preparing the final answer.

---

<div class="post-metadata">

**Author:** ![swi](https://avatars.discourse-cdn.com/v4/letter/s/51bf81/32.png) [@swi](https://swi-prolog.discourse.group/u/swi)\
**Post date:** [November 12, 2020, 5:59pm UTC](https://swi-prolog.discourse.group/t/distinguish-undefined-from-true-or-false/3253/11 "2020-11-12T17:59:47Z")

</div>

> [@jan](#):
>
> Don’t ask me 🙂 I implemented this stuff with the help of Theresa Swift and David S. Warren, but so far I did little with it except for playing …

Hehehehe you are funny 😁

> [@jan](#):
>
> ```prolog
> ?- findall(X,call_delays(shaves(barber,X),true), Xs).
> 
> ```
> 
> And to get the undefined ones
> 
> `?- findall(X,(call_delays(shaves(barber,X),Delays), Delays \== true), Xs).`

This gives me a good idea; I wasn’t so off track as I thought.

> [@jan](#):
>
> […] except for preparing the final answer.

This is what I was thinking about.
