# Surprising result with equals dot dot

**URL:** <https://swi-prolog.discourse.group/t/surprising-result-with-equals-dot-dot/4989>\
**Category:** Help!\
**Tags:** functor\
**Created:** [February 7, 2022, 8:27pm UTC](https://swi-prolog.discourse.group/t/surprising-result-with-equals-dot-dot/4989 "2022-02-07T20:27:24Z")\
**Posts on this page:** 17\
**Page:** 1

<div class="post-metadata">

**Author:** ![brebs](https://avatars.discourse-cdn.com/v4/letter/b/e9c0ed/32.png) [@brebs](https://swi-prolog.discourse.group/u/brebs)\
**Post date:** [February 7, 2022, 8:27pm UTC](https://swi-prolog.discourse.group/t/surprising-result-with-equals-dot-dot/4989/1 "2022-02-07T20:27:24Z")

</div>

Using SWI-Prolog version 8.5.7

```prolog
?- X = (2, 3), X =.. Y, length(Y, YLen), nth1(1, Y, Y1).
X = (2,3),
Y = [,,2,3],
YLen = 3,
Y1 = (,).

```

Is it correct for Y1 to ever be a tuple? Why default to such a confusing display of Y, which looks like a list of 4 elements?

---

<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:** [February 7, 2022, 8:52pm UTC](https://swi-prolog.discourse.group/t/surprising-result-with-equals-dot-dot/4989/2 "2022-02-07T20:52:53Z")

</div>

Maybe this explains things - with `write_canonical(Y1)` (using format/3, to get it into a `Y1str` as a string):

```prolog
?- X = (2, 3), X =.. Y, length(Y, YLen), nth1(1, Y, Y1), format(string(Xstr), '~k', [X]), format(string(Y1str), '~k', [Y1]).
X = (2, 3),
Y = [',', 2, 3],
YLen = 3,
Y1 = (','),
Xstr = "','(2,3)",
Y1str = "','".

```

I’m also using 8.5.7, so it’s curious that your output is different.

---

<div class="post-metadata">

**Author:** ![brebs](https://avatars.discourse-cdn.com/v4/letter/b/e9c0ed/32.png) [@brebs](https://swi-prolog.discourse.group/u/brebs)\
**Post date:** [February 7, 2022, 9:41pm UTC](https://swi-prolog.discourse.group/t/surprising-result-with-equals-dot-dot/4989/3 "2022-02-07T21:41:26Z")

</div>

Aah, this is what unintentionally adjusted my write settings to remove the single quotes (was in my ~/.config/swi-prolog/init.pl ) :

```prolog
:- set_prolog_flag(answer_write_options,[max_depth(100)]).

```

I was expecting that, since I was not changing the other defaults, that they would keep their usual, sensible values 😀  
I have changed it to:

```prolog
:- set_prolog_flag(answer_write_options, [quoted(true), portray(true), max_depth(100), attributes(portray)]).

```

Does Y1, as a comma, make sense?

---

<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:** [February 8, 2022, 12:11am UTC](https://swi-prolog.discourse.group/t/surprising-result-with-equals-dot-dot/4989/4 "2022-02-08T00:11:23Z")

</div>

> [@brebs](#):
>
> Does Y1, as a comma, make sense?

Yes. In this context, comma is an operator:

```prolog
?- X = (a, b).
X = (a, b).

?- current_op(Precedence, Type, ',').
Precedence = 1000,
Type = xfy.

```

---

<div class="post-metadata">

**Author:** ![brebs](https://avatars.discourse-cdn.com/v4/letter/b/e9c0ed/32.png) [@brebs](https://swi-prolog.discourse.group/u/brebs)\
**Post date:** [February 8, 2022, 12:33am UTC](https://swi-prolog.discourse.group/t/surprising-result-with-equals-dot-dot/4989/5 "2022-02-08T00:33:36Z")

</div>

I meant, why does Y1 involve a comma, when presumably it should be blank, since I specified `(2, 3)` instead of `term_name_here(2, 3)`.

As opposed to the perfectly normal question and answer of:

```prolog
?- X = normal_term(2, 3), X =.. Y, length(Y, YLen), nth1(1, Y, Y1).
X = normal_term(2,3),
Y = [normal_term,2,3],
YLen = 3,
Y1 = normal_term.

```

---

<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:** [February 8, 2022, 1:21am UTC](https://swi-prolog.discourse.group/t/surprising-result-with-equals-dot-dot/4989/6 "2022-02-08T01:21:40Z")

</div>

> [@brebs](#):
>
> why does Y1 involve a comma, when presumably it should be blank,

As you can see, there is no distinction between a term that’s specified with an operator and one that’s given in “prefix” form:

```prolog
?- (a,b) = ','(a,b)
true

```

Perhaps this is clearer:

```prolog
?- (a+b) = '+'(a,b).
true.

```

The only place where comma _isn’t_ an operator is for separating the arguments in a term; everywhere else, it’s an operator. Compare:

```prolog
?- write_canonical(p(a,b)).
p(a,b)

?- write_canonical(p((a,b))).
p(','(a,b))

?- write_canonical(p((a,b),c)).
p(','(a,b),c)

?- write_canonical(p((a,b),(c,d))).
p(','(a,b),','(c,d))

```

---

<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:** [February 8, 2022, 5:03am UTC](https://swi-prolog.discourse.group/t/surprising-result-with-equals-dot-dot/4989/7 "2022-02-08T05:03:53Z")

</div>

I guess your question got answered already? The bottom line is, this:

```
(2, 3)

```

is **not** an “anonymous tuple” or anything of the sort. It is **not** the same as `foo(2, 3)` with just the “foo” missing.

```
foo(2, 3)

```

is a compound term with name “foo”, arity 2, and the two arguments are `2, 3`.

```
(2, 3)

```

happens to parse as a compound term with name “`,`”, arity 2, and arguments `2, 3`, **because `,` is an operator**. This is why this succeeds:

```prolog
?- (2, 3) = ','(2, 3).
true.

```

Note that here the “`','`” is indeed an atom of length one.

This fails:

```prolog
?- (2, 3) = ,(2, 3).
ERROR: Syntax error: Operator expected
ERROR: (2, 3) = 
ERROR: **here**
ERROR: ,(2, 3) . 

```

Why does it fail and why do you think that it is [“not allowed to redefine the comma”](https://www.swi-prolog.org/pldoc/doc_for?object=op/3)?

PS: I suspect or maybe faintly remember that with a different parser there might be a Prolog that allows you to redefine the comma.

---

<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:** [February 8, 2022, 7:44am UTC](https://swi-prolog.discourse.group/t/surprising-result-with-equals-dot-dot/4989/8 "2022-02-08T07:44:48Z")

</div>

There is a so-called “comma list”, but its use is frowned upon as bad style; and a “regular” list is easier. Here’s an example (it works because the “`,`” operator is right-associative:  
`(a,b,c) = ','(a,','(b,c))`:

```prolog
% don't do this
sum_comma_list((X,Xs), Sum) :- !, % this cut is needed
    sum_comma_list(Xs, Sum0),
    Sum is X + Sum0.
sum_comma_list(X, X). % X \= (_,_)

?- sum_list([1,2,3], Sum).
Sum = 6.

```

Here is better style (notice that it doesn’t need a cut and the clauses can be in any order and it also allows a 0-length list, whereas a “comma list” must have at least one item):

```prolog
sum_list([X|Xs], Sum) :-
    sum_list(Xs, Sum0),
    Sum is X + Sum0.
sum_list([], 0).

?- sum_comma_list((1,2,3), Sum).
Sum = 6.

```

---

<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:** [February 8, 2022, 9:57am UTC](https://swi-prolog.discourse.group/t/surprising-result-with-equals-dot-dot/4989/9 "2022-02-08T09:57:30Z")

</div>

My favorite demonstration about the pitfalls of comma lists (as seen somewhere on the internets):

```prolog
?- [A, B] = [A, B, C].
false. % of course

?- (A, B) = (A, B, C).
B = (B, C). % WAT?

```

Coming from a language that has “tuples” this second query should come as a nasty surprise. It also shows why comma lists are not tuples in the widely accepted meaning of the word “tuple”.

And of course `[]` (the empty list) is a thing while `()` (the empty tuple?) is not a thing, as you mention.

Both Python (hugely popular) and Haskell (hugely popular in some circles) have tuples that look like `(a, b)`; and Prolog accepts this construct, and it seems to work. The end result is that you see a lot of Prolog code that uses those, some of it apparently coming from people teaching Prolog to other people, within the safe space of educational institutions.

---

<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:** [February 8, 2022, 10:07am UTC](https://swi-prolog.discourse.group/t/surprising-result-with-equals-dot-dot/4989/11 "2022-02-08T10:07:53Z")

</div>

Thank you, you are correct. However, no one who wants to use “tuples in Prolog” would start adding `true` as the last element of all their tuples, I thought. Maybe I am wrong.

---

<div class="post-metadata">

**Author:** ![grossdan](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/grossdan/32/23_2.png) [@grossdan](https://swi-prolog.discourse.group/u/grossdan)\
**Post date:** [February 8, 2022, 10:14am UTC](https://swi-prolog.discourse.group/t/surprising-result-with-equals-dot-dot/4989/12 "2022-02-08T10:14:18Z")

</div>

Sometimes, when i have a goal/predicate as so pred(A, B) :- and i need to add an argument without adding causing pred/2 to become pred/3, I pass something like (X, Y) to bind with, say, B.

When placed before the original pred/2, these get found first.

Usually, its to try out things and to later rework the code without such contraption …

But, its a quick way to add an argument …

---

<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:** [February 8, 2022, 10:17am UTC](https://swi-prolog.discourse.group/t/surprising-result-with-equals-dot-dot/4989/14 "2022-02-08T10:17:27Z")

</div>

Do not do that. Use a pair, `X-Y` or just name your “tuple” somehow:

```prolog
pred(A, B) -----> pred(A, X-Y)

```

or maybe

```prolog
pred(A, B) -----> pred(A, x(X, Y))

```

I would call comma lists a “code smell” but the word “smell” is too nice 😉

---

<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:** [February 8, 2022, 10:18am UTC](https://swi-prolog.discourse.group/t/surprising-result-with-equals-dot-dot/4989/15 "2022-02-08T10:18:50Z")

</div>

Yes, I use `v(a, b, c)` with the mnemonic “vector” or maybe “values”, if it is really so generic that I cannot come up with a short word that describes my `a, b, c` any better.

---

<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:** [February 8, 2022, 10:31am UTC](https://swi-prolog.discourse.group/t/surprising-result-with-equals-dot-dot/4989/16 "2022-02-08T10:31:43Z")

</div>

AFAIK, O’Keefe’s “The Craft of Prolog” already claims “never use a list for something of a fixed number of elements”. Instead, use a tuple as a compound term and try to give it a sensible name. For anonymous tuples with two arguments, use `A-B` which works nicely with library(pairs), keysort/2 and similar built-ins and libraries. I also tend to use v(…) if I see no need for a sensible name 🙂

---

<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:** [February 8, 2022, 6:02pm UTC](https://swi-prolog.discourse.group/t/surprising-result-with-equals-dot-dot/4989/17 "2022-02-08T18:02:59Z")

</div>

The form `A-B` tends to be used with the implied semantics `Key-Value`, and that can lead to subtle bugs if you assume the Keys are unique (I just fixed some code that made such a mistake), even though keysort/2 explicitly makes no assumption about uniqueness of keys.  
I’ve also seen `A-B` used for difference lists (and sometimes `A\B`), with the mental image of subtracting `B` from the end of `A`.

As others have said, best to use a tuple; `v(A,B,C)` is better than `A-B-C` (and also slightly more efficient), and even better if you can use something more meaningful than “`v`” for the functor name.

---

<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:** [February 8, 2022, 7:01pm UTC](https://swi-prolog.discourse.group/t/surprising-result-with-equals-dot-dot/4989/18 "2022-02-08T19:01:08Z")

</div>

The “minus” as in `A-B` is only good for a pair, it doesn’t extend to `A-B-C`. That suffers the exact same problem as “comma lists”, BTW, just swapped:

```prolog
?- A-B = A-B-C.
A = A-C,
B = C.

```

The “clean” way to extend `-` from a pair to a triple, quadriple etc would be to do the exact same thing you’d do with the comma:

```prolog
','(a, b), ','(a, b, c), ','(a, b, c, d)
-(a, b), -(a, b, c), -(a, b, c, d)

```

what I now learned and find curious is that others also use `v(a, b, ...)` for this.

---

<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:** [February 8, 2022, 9:39pm UTC](https://swi-prolog.discourse.group/t/surprising-result-with-equals-dot-dot/4989/20 "2022-02-08T21:39:03Z")

</div>

There is a lot of interesting lessons to be learned from R. IIRC the `c()` in R is a function that _ **c** ombines_ or maybe _ **c** oncatenates_ its arguments to a one-dimensional vector (and it takes as many arguments as you give it…).

It seems that ECLiPSe has a very similar interface to arrays as R. In R at least you can at run time change the dimensions of an array (efficiently) by [assigning a vector of dimensions to your array](https://cran.r-project.org/doc/manuals/r-release/R-intro.html#index-dim).
