Noname operators

Ulrich Neumerkel, 2010-07-08 (Version history)
We explore the presence of operators in 13211-1 that are not names and propose to remove two misleading and frequently unsupported operators. Further, we propose to add a new operator | (bar).
Most operators in ISO/IEC 13211-1:1995 are names (6.4.2). The well known exception is the unquoted comma which is no name and thus cannot be used unquoted as an atom. Unquoted, comma can only be used as an infix right-associative operator of priority 1000—apart from its uses in functional notation and list notation.

Two operators as source of ambiguity

In addition to the comma, 13211-1:1995 also permits the unquoted [ ] and { } to serve as operators. Remark that unquoted [ ] and { } are atoms but not names. With an operator declaration op(600,xfy,[]) the following four examples are valid Prolog text.
1[]2.
1[]2[]3.
[1][][2].
[1][/*comment within operator*/][2].
All systems tested permit an operator declaration for []. But only one system recognizes above examples as valid Prolog text: SWI. The other systems tested were B, CIAO, DEC-10, ECLiPSe, GNU, IF, Qu, SICStus, XSB, YAP. They produce a syntax error for all examples. However, all systems recognize the operator when being quoted. But in that case, the operator is a name.

[] as prefix operator can change common syntax. For example, the list [[a]-[b],[]-[b]]. with a declaration op(600,fx,[]) now corresponds to [-([a],[b]),[](-([b]))]. While the first element remains unaltered as expected, the second one changes its meaning. This appears very unintuitive, since removing an element from a list should not change the principal meaning of a term. This behavior can be observed in GNU, IF and SWI. CIAO, SICStus show this behaviour only with the operator declaration op(600,fx,[[]]). Similar problems arise with {} as operators.

In conclusion, the unquoted [] and {} as operators make elementary list syntax very brittle. The poor support by existing systems suggest that [] and {} as operators entered the standard rather accidentally. Also the change history between N92 and the final standard suggests an accidental erosion which is listed below.

N92 1st CD 1992-03
6.3.4.3 Operators: op = name ; op = comma ;
NOTES
3 the third argument of op/3 (8.14.13) is any name except ',',
'[]', and '{}', so the precedence of the comma operator cannot be
changed, and so empty lists and curly bracket pairs cannot be treated
as operators.
N110 revised CD 1993-03
6.3.4.3 Operators: op = name ; op = comma ;
NOTES
3 the third argument of op/3 (8.14.13) is any name except ',',
'[]', and '{}', so the precedence of the comma operator cannot
be changed, and so empty lists and a curly brackets cannot be treated
as operators.
N128 DIS 13211-1 1994-03
6.3.4.3 Operators: op = name ; op = comma ;
NOTES
3 The third argument of op/3 (8.14.3) is any atom except
',' so the priority of the comma operator cannot be changed.
ISO/IEC 13211-1 1995-06-01
6.3.4.3 Operators: op = atom ; op = comma ;
NOTES
3 The third argument of op/3 (8.14.3) may be any atom
except ',' so the priority of the comma operator cannot be
changed.

Removal options

Change 6.3.4.3 Operators from
An operator is an atom (6.3.1.3).

A comma (6.4.8) shall be equivalent to the atom ','
when ',' is an operator

op = atom ; op = comma ;
to
An operator is a name or a comma (or a bar) (6.4).

A comma (6.4) shall be equivalent to the atom ','
when ',' is an operator.

op = name ; op = comma ;
Add at the end of 6.3.4.3
There shall not be an operator with name '{}' or '[]'.
(Optionally) Change 6.3.4.3, NOTE 3 to:
3 The third argument of op/3 (8.14.3) may be any atom
except ',', '[]', and '{}' so the priority of the comma
operator cannot be changed, and so empty lists and curly
bracket pairs cannot be treated as operators
.
(Optionally) Add to 8.14.3.4 Examples
op(300, fx, '[]').
   permission_error(create, operator, []).
op(300, fx, '{}').
   permission_error(create, operator, {}).
This error is due to error condition 8.14.3.3 l, which applies since the set of specifiers {fx} for '[]' and '{}' is invalid.

Addition of the bar

As discussed in N220, the addition of the bar | as an infix operator might be considered desirable. In case of agreement, the bar may be introduced similarly to the comma operator. Open to discussion is the precise treatment within op/3 (8.14.3). I.e. shall | be changeable or not.
Add to 6.3.4.3 Operators
A bar shall be equivalent to the atom '|' when '|' is an infix operator.
op = bar ;
Abstract:|
Priority:1105
Specifier:xfy
Add to 6.4 Tokens
bar (* 6.4 *)
   = ht sep (* 6.4 *)
Alternatively, but more costly (all subsequent changes are now necessary):
bar (* 6.4 *)
   = [ layout text sequence (* 6.4.1 *) ] ,
     bar token (* 6.4.8 *) ;
Add to 6.4.8 Other tokens
bar token (* 6.4.8 *)
  = bar char (* 6.5.3 *) ;
Add to 6.5.3 Solo characters
Additional alternative for solo char:
  | bar char (* 6.5.3 *)
bar char (* 6.5.3 *) = "|" ;

Reconstructed DEC-10 behavior

The DEC-10 Prolog parser of D.H.D.Warren and Richard O'Keefe dated 1984-07-05 does accept neither [] nor {} as operators. Below is an analysis of file read.pl as contained in Note No. 103, AIAI/PSG103/87, University of Edinburgh 1987-11-12.

Infix and postfix not supported

A syntax error is produced for all Prolog texts starting with 1[ and 1{ regardless of the presence of operator declarations.

To see this, it is sufficient to consider the following slice of the DEC-10 Prolog parser using the tokens integer(1) and '['.

?- read([integer(1),'['| Anything], 1200, Term, LeftOver).

read(integer(Integer), S0, Precedence, Answer, S) :- !,
	exprtl0(S0, Integer, Precedence, Answer, S).

exprtl0([atom(F)|S1], Term, Precedence, Answer, S) :- ... .
exprtl0([atom(F)|S1], Term, Precedence, Answer, S) :- ... .
exprtl0([atom(F)|S1], Term, Precedence, Answer, S) :- ... .
exprtl0([','|S1], Term, Precedence, Answer, S) :- ... .
exprtl0(['|'|S1], Term, Precedence, Answer, S) :- ... .
exprtl0([Thing|S1], _, _, _, _) :-
	cant_follow_expr(Thing, Culprit), !,
	syntax_error([Culprit,follows,expression], [Thing|S1]).

... .
cant_follow_expr('[',		bracket).
cant_follow_expr('{',		bracket).

Prefix not supported

All Prolog texts starting with []1 produce a syntax error regardless of the operator declarations.
?- read(['[',']',integer(1)| Anything], 1200, Term, LeftOver).

read('[', [']'|S1], Precedence, Answer, S) :- !,
	exprtl0(S1, [], Precedence, Answer, S).

exprtl0([atom(F)|S1], Term, Precedence, Answer, S) :- ... .
exprtl0([atom(F)|S1], Term, Precedence, Answer, S) :- ... .
exprtl0([atom(F)|S1], Term, Precedence, Answer, S) :- ... .
exprtl0([','|S1], Term, Precedence, Answer, S) :- ... .
exprtl0(['|'|S1], Term, Precedence, Answer, S) :- ... .
exprtl0([Thing|S1], _, _, _, _) :-
	cant_follow_expr(Thing, Culprit), !,
	syntax_error([Culprit,follows,expression], [Thing|S1]).

... .
cant_follow_expr(integer(_),	integer).
... .


Richard O'Keefe:

>When you are working on modal logic in Prolog, you most
>*definitely* want to be able to write
>        P & [](P -> Q) -> Q
>        P -> <>P
>where [] is the "necessarily" operator
>   and <> is the "possibly" operator.

Here is a clean alternative in UTF-8, that seems to be much better
readable:

:- op(900,fy,'\x25a1\').  % Necessarily
:- op(900,fy,'\x25ca\').  % Possibly
:- op(900,fy,□).  % Necessarily
:- op(900,fy,◊).  % Possibly