# Composite term not checked

**URL:** <https://swi-prolog.discourse.group/t/composite-term-not-checked/6912>\
**Category:** Help!\
**Created:** [October 23, 2023, 3:40pm UTC](https://swi-prolog.discourse.group/t/composite-term-not-checked/6912 "2023-10-23T15:40:22Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![marceloslacerda](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/marceloslacerda/32/5769_2.png) [@marceloslacerda](https://swi-prolog.discourse.group/u/marceloslacerda)\
**Post date:** [October 23, 2023, 3:40pm UTC](https://swi-prolog.discourse.group/t/composite-term-not-checked/6912/1 "2023-10-23T15:40:22Z")

</div>

I’m using: SWI-Prolog version 9.0.4

Why does this prolog program:

```prolog
mycomp(a, b).

mypred(X):-
  X=mycomp(_, _).

```

Unify with `?- mypred(mycomp(z, w)).` ?

I would have guessed that prolog would fail because `z` and `w` are not valid terms for `mycomp`. How would I have to rewrite my program for that to happen?

---

<div class="post-metadata">

**Author:** ![Boris](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/boris/32/7486_2.png) [@Boris](https://swi-prolog.discourse.group/u/Boris)\
**Post date:** [October 23, 2023, 6:08pm UTC](https://swi-prolog.discourse.group/t/composite-term-not-checked/6912/2 "2023-10-23T18:08:34Z")

</div>

> [@marceloslacerda](#):
>
> ```prolog
> mypred(X):-
> X=mycomp(_, _).
> 
> ```

As discussed earlier, this is equivalent to:

```prolog
mypred(mycomp(_, _)).

```

Since the underscore is an anonymous variable, it will match anything. In particular:

```prolog
?- mycomp(z, w) = mycomp(_, _).
true.

```

> [@marceloslacerda](#):
>
> I would have guessed that prolog would fail because `z` and `w` are not valid terms for `mycomp`. How would I have to rewrite my program for that to happen?

I don’t quite get your question.

---

<div class="post-metadata">

**Author:** ![marceloslacerda](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/marceloslacerda/32/5769_2.png) [@marceloslacerda](https://swi-prolog.discourse.group/u/marceloslacerda)\
**Post date:** [October 23, 2023, 6:44pm UTC](https://swi-prolog.discourse.group/t/composite-term-not-checked/6912/3 "2023-10-23T18:44:47Z")

</div>

> mypred(mycomp(\_, \_)).

Seems pretty obvious now that you wrote it 😁

> I don’t quite get your question.

What’s the elegant way of defining a predicate mypred(X) that only holds if X is a compound term mycomp(Z,W)?

The best I can think of now is something like:

```prolog
mycomp(a, b).

mypred(mycomp(X, Y)):-
  mycomp(X, Y).

```

But it seems redundant to mention mycomp twice in the same predicate.

More generally, what’s the usual way that data encapsulation is done in prolog?

---

<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:** [October 23, 2023, 6:58pm UTC](https://swi-prolog.discourse.group/t/composite-term-not-checked/6912/4 "2023-10-23T18:58:25Z")

</div>

This does the equivalent of what your “best I can think of” code does:

```prolog
mypred(mycomp(a,b)).

```

But, from your question, you seem to be asking something different. Did you mean this?

```prolog
mypred(mycomp(_Z,_W)).

```

---

<div class="post-metadata">

**Author:** ![Boris](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/boris/32/7486_2.png) [@Boris](https://swi-prolog.discourse.group/u/Boris)\
**Post date:** [October 23, 2023, 6:58pm UTC](https://swi-prolog.discourse.group/t/composite-term-not-checked/6912/5 "2023-10-23T18:58:36Z")

</div>

Hmmm… In the head of the predicate, `mycomp(X,Y)` is a Prolog term. In the body, it is a goal that you evaluate (or query…).

> [@marceloslacerda](#):
>
> What’s the elegant way of defining a predicate mypred(X) that only holds if X is a compound term mycomp(Z,W)?

This is it:

```prolog
mypred(mycomp(Z, W)).

```

But now both are “singleton variables” without any further constraints on them, so that will succeed for any Z and any W.

What kind of data encapsulation do you mean? This sounds like a technique, not an aim…

When you say “compound term”, you do realize this is really just a data structure and not a predicate? You can evaluate it as a predicate though, this is what happens if you put it in the place of a goal.

I still have a feeling this is a terminology confusion 😅

EDIT: if you want to pass a predicate to a predicate, then you have define a meta-predicate. There is nothing special about it, really. For example, maplist is a meta-predicate, so you can do something like this:

```prolog
?- maplist(plus(1), [2,3], Result).
Result = [3, 4].

```

This is equivalent to:

```prolog
?- plus(1, 2, X), plus(1, 3, Y), Result = [X, Y].

```

Is that at all relevant for your question??

---

<div class="post-metadata">

**Author:** ![Ian](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/ian/32/1026_2.png) [@Ian](https://swi-prolog.discourse.group/u/Ian)\
**Post date:** [October 23, 2023, 8:38pm UTC](https://swi-prolog.discourse.group/t/composite-term-not-checked/6912/6 "2023-10-23T20:38:38Z")

</div>

I suspect the OP is looking for:

```prolog
mypred(X):-
  X=mycomp(_,_),
  X.

```

Possibly with a `ground(X)` in the middle if only explicit facts are required.

---

<div class="post-metadata">

**Author:** ![CapelliC](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/capellic/32/17_2.png) [@CapelliC](https://swi-prolog.discourse.group/u/CapelliC)\
**Post date:** [October 24, 2023, 6:01am UTC](https://swi-prolog.discourse.group/t/composite-term-not-checked/6912/7 "2023-10-24T06:01:06Z")

</div>

I think you should try the good old clause/2:

```prolog
?- [user].
|: mypred(X) :- clause(X, true).
|: 
% user://1 compiled 0.00 sec, 1 clauses
true.

?- [user].
|: mycomp(a, b).
|: 
% user://2 compiled 0.00 sec, 1 clauses
true.

?- mypred(mycomp(z, w)).
false.

?- mypred(mycomp(A, B)).
A = a,
B = b.

```

(PS: where you see

```prolog
% user://1 compiled 0.00 sec, 1 clauses

```

it means I’ve closed the input stream, hitting Ctrl+Z)

---

<div class="post-metadata">

**Author:** ![Boris](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/boris/32/7486_2.png) [@Boris](https://swi-prolog.discourse.group/u/Boris)\
**Post date:** [October 24, 2023, 8:31am UTC](https://swi-prolog.discourse.group/t/composite-term-not-checked/6912/8 "2023-10-24T08:31:10Z")

</div>

> [@CapelliC](#):
>
> I’ve closed the input stream, hitting Ctrl+Z

This is of course on Windows, on \*nix it is Ctrl+D. Ctrl+Z will stop your process.

---

<div class="post-metadata">

**Author:** ![marceloslacerda](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/marceloslacerda/32/5769_2.png) [@marceloslacerda](https://swi-prolog.discourse.group/u/marceloslacerda)\
**Post date:** [October 24, 2023, 11:07am UTC](https://swi-prolog.discourse.group/t/composite-term-not-checked/6912/9 "2023-10-24T11:07:46Z")

</div>

Is there any difference between

```prolog
my_pred(X):- X.

```

and

```prolog
my_pred(X):- clause(X, true).

```

?

---

<div class="post-metadata">

**Author:** ![Boris](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/boris/32/7486_2.png) [@Boris](https://swi-prolog.discourse.group/u/Boris)\
**Post date:** [October 24, 2023, 11:25am UTC](https://swi-prolog.discourse.group/t/composite-term-not-checked/6912/10 "2023-10-24T11:25:11Z")

</div>

One obvious difference is that this:

> [@marceloslacerda](#):
>
> `my_pred(X):- X.`

really just evaluates X. You can give it anything:

```prolog
?- [user].
|: my_pred(X) :- X.
|: ^D% user://1 compiled 0.00 sec, 1 clauses
true.

?- my_pred(format("hello!~n", [])).
hello!
true.

```

If you use clause/2 with `true` as the second argument then this will certainly fail.

By the way, this definition:

> [@marceloslacerda](#):
>
> `my_pred(X):- X.`

looks a lot like [call](https://www.swi-prolog.org/pldoc/doc_for?object=call/1), doesn’t it? Even the docs say:

> Note that a plain variable as a body term acts as [call/1](https://www.swi-prolog.org/pldoc/man?predicate=call/1) …

---

<div class="post-metadata">

**Author:** ![CapelliC](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/capellic/32/17_2.png) [@CapelliC](https://swi-prolog.discourse.group/u/CapelliC)\
**Post date:** [October 24, 2023, 6:28pm UTC](https://swi-prolog.discourse.group/t/composite-term-not-checked/6912/12 "2023-10-24T18:28:36Z")

</div>

They are so much different, like day and night…  
The first form is using call/1, the second instead is using reflection, and this means that the first one **executes** the code, while the second one **lists** (kind of) it.

---

<div class="post-metadata">

**Author:** ![marceloslacerda](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/marceloslacerda/32/5769_2.png) [@marceloslacerda](https://swi-prolog.discourse.group/u/marceloslacerda)\
**Post date:** [October 25, 2023, 3:25pm UTC](https://swi-prolog.discourse.group/t/composite-term-not-checked/6912/13 "2023-10-25T15:25:19Z")

</div>

I was so happy with Ian’s solution (and I’ve used it so much) that I made my own predicate to encapsulate it:

```prolog
of_type(Variable, CompoundTerm):-
    Variable=CompoundTerm,
    CompoundTerm.

```

That I test with:

```prolog
test_compound(a, b).

test_of_type(X, Y, Z):-
  of_type(X, test_compound(Y, Z)).

```

```prolog
?- test_of_type(a, b, c).
false.

?- test_of_type(a, X, Y).
false.

?- test_of_type(test_compound(X, Y), X, Y).
X = a,
Y = b.

?- test_of_type(test_compound(_, _), X, Y).
X = a,
Y = b.

?- test_of_type(test_compound(z, w), X, Y).
false.

```
