Why is `-` the functor for pairs?

I’m not expecting to rewrite the history of Prolog and its conventions.

But if I’m writing pair literals, my intuition/preference would be that
a-b-c parses as
-(a,-(b,c)) instead of -(-(a,b),c)

If : was the pairs functor, I’d get what I’d expect.
And, in fact, Dicts use :, so perhaps my expectations are reasonable.

In any case, are there some particularly useful results (in terms of expressiveness or clarity of code) that come from using - as the pair functor?

1 Like

Good to hear :sweat_smile:

For the answer you have to wait that one of the core developers speaks his mind

There is probably no reason other than historical accident. Currently it is used for Key-Value pairs by keysort/2 and library(pairs) so there is a good enough reason to continue using it.

This is questionable no matter which operator precedence you have. All of these share the same problem, see this post and the posts above it. For example:

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

?- A:B:C = A:B.
B = B:C.

I guess you’d hope both queries would fail? For that, you need to use a flat term, something like v(A,B,C).

PS: if the second element of the pair is supposed to be a “negative number”, like -2, both - and : are problematic in different ways…

?- display(1--2).
ERROR: Syntax error: Operator expected
ERROR: display(
ERROR: ** here **
ERROR: 1--2) . 

?- display(1- -2). % this works....
-(1,-2)
true.

?- display(1:-2). % this seems to work but it doesn't
:-(1,2)
true.

(:)/2 is not part of the ISO core standard.
Its part of the ISO module standard. The operator
is not listed in the ISO core standard operator table:

ISO core standard operator table:
image

So from the point of view of ISO core standard, things
like keysort/2 that expect pairs, didn’t use (:)/2, but rather
(-)/2 which was within reach.

Edit 06.03.2024
The (:)/2 operator then pops up in the ISO module standard,
explicitly mentioned in section 5.2.1 Operators, which also says
that each module has its own operator table:

The module operator is 600 xfy :, which has different associativity
specifier than 500 yfx -. This explains the different reading
of A-B-C as (A-B)-C versus A:B:C as A:(B:C):

ISO module standard operator table:
image

Whats missing in the above table is the (@)/2 operator
used for example in section 6.4.4 Examples: Metapredicates
of the ISO module standard.

1 Like

I have tested the -/2 operator in arithmetic to have found it is defined as left associative operator. I have noticed that if a value part of assoc list is a ‘-’ term, it might cause unexpected error if - is used for pairing.

?- X is 10 - 5 - 2.
X = 3.
?- X is (10 - 5) - 2.
X = 3.
?- X is 10 - (5 - 2).
X = 7.