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.
[ ]
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.
All systems tested permit an operator declaration for1[]2. 1[]2[]3. [1][][2]. [1][/*comment within operator*/][2].
[]
.
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.
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.
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.
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.
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.
An operator is an atom (6.3.1.3).to
A comma (6.4.8) shall be equivalent to the atom','
when','
is an operator
op = atom ; op = comma ;
An operator is a name or a comma (or a bar) (6.4).Add at the end of 6.3.4.3
A comma (6.4) shall be equivalent to the atom','
when','
is an operator.
op = name ; op = comma ;
There shall not be an operator with name(Optionally) Change 6.3.4.3, NOTE 3 to:'{}'
or'[]'
.
3 The third argument of op/3 (8.14.3) may be any atom(Optionally) Add to 8.14.3.4 Examples
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.
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.
|
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.
op = bar ;
Abstract: | Priority: 1105 Specifier: xfy
bar (* 6.4 *) = ht sep (* 6.4 *)
bar (* 6.4 *) = [ layout text sequence (* 6.4.1 *) ] , bar token (* 6.4.8 *) ;
bar token (* 6.4.8 *) = bar char (* 6.5.3 *) ;
solo char
:
| bar char (* 6.5.3 *)
bar char (* 6.5.3 *) = "|" ;
[]
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.
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).
[]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