Using '||' as operator?

I understand the restrictions on ‘|’ as an operator, but what about ‘||’? Defining it with op/3 seems to be fine but when it’s used, the parser seems to get struck:

?- current_op(P,A,'||').
P = 500,
A = yfx.

?- X = a||b.

Action (h for help) ? |    abort
% Execution Aborted

You have defined '||'/2 as operator, not ||/2. So you should use X = a'||'b.

I think there’s more to it. The atom defined by || should be exactly equivalent to '||'. In fact if I define the operator as:

op(500, yfx, ||).

and query it:

?- current_op(500,A,F).
A = yfx,
F =  ('||') .

Note that || (without the quotes was just fine inside the op/3 definition.

An even simpler test; nothing to do with operators:

?- X = ++ .
X = ++ .

?- X = || .

Action (h for help) ? |    abort
% Execution Aborted

An operator that requires quoting isn’t particularly useful IMO.

I get an error:

?- [user].
test(X) :- X = (||).
ERROR: user://1:8:24: Syntax error: end_of_file_in_quasi_quotation

That error message is probably a good clue although I’m not sure how quasi quotations get involved in this.

My best guess is that term reading already does something special with a single bar; you never get to the second bar.

Quasy quotations get dragged in probably because there is a special case for term reading for quasy quotations. Since those are written as:


They need special treatment for the double bar. But at this point you are inside the {|.

The fact that reading with || seems to be non-terminating is a bug. Other then that, | is a singleton and thus should never glue to a longer atom without using quotes. There is simply now way to turn || into legal syntax, which is why it was chosen to act in quasi quotations.

1 Like

Digging a little deeper, I see that, according to the manual, SWIP syntax is founded on ISO Prolog syntax. I, and I suspect the vast majority of Prolog users, aren’t going to pay money to the standards organization for the privilege of using it, so I went to the Eclipse documentation for the syntax definition of atom:

ATOM    = (LC ALP*)
        | (SY | CM1 | CM2 | ES)+
        | (AQ (NES | ESCSEQ)* AQ)
        | SL
        | []
        | {}
        | |

and indeed | is a singleton atom and not allowed in a “symbolic” atom (second alternative). Alas, another useful operator character lost.

So is Eclipse syntax equivalent to ISO syntax in this regard? Possibly a lot of work, but perhaps the SWIP manual needs an expanded syntax section equivalent to the Eclipse Syntax Appendix.

You dont pay any money for using the ISO core standard. Only the documents have a price. But there is no royality to be payed if your Prolog system has some ISO core standard compliance.

The syntax of atoms and strings is:

         | SY+
         | (AQ (NES | ESCSEQ)* AQ)
         | SO
         | []
         | {}

SO    = '|' 
      | ','
      | ;
      | ! 

The vertical bar belongs to the so called solo characters. I named the production ATOMSTR, since what happens with AQ depends on the flags double_quotes etc…

I have written the solo characters ‘|’ and ‘,’ with quotes, since they are not always valid atoms unquoted. There is some finess concerning whether the atom is used as an operator or not.

The SWI-Prolog parser even emits an error explaining the finess:

?- X = (a | b).
X =  (a| b).

?- X = | .
ERROR: Syntax error: Operand expected, unquoted comma or bar found

Sorry, I should have said for the privilege of reading their document.

Thanks for sharing the atom syntax specification. Perhaps you could also provide the BNF for LC (assume lowercase letters), ALP (assume alphanumerics), and SY (equivalent to Eclipse definition?).

It depends how you handle things beyond ASCII. The ISO core standard only describes an ASCII variant. But many Prolog systems have extended their system for example to Unicode. So what is a lower case in Unicode? SWI-Prolog is also no exception, today I was happily doing in some Prolog text the following operator definition, which is beyond ASCII:

:- encoding(utf8).

:- op(100, xfx, ∈).

But it didn’t work so well on my Mac today. It turned out that current_prolog_flag(encoding, X) gave me X = text, and text could not deal with it. Globally setting set_prolog_flag(encoding, utf8) didn’t work, since I had an import, and the imported file had always an error. So I placed the encoding/1 directive inside the Prolog texts.

If SWI-Prolog had the default of utf8 instead of text, this could be more useful.

Edit 05.02.2021:
If you want double bar, you could also try Unicode. But I am not sure whether it would fit your needs:

?- X = ‖ , char_code(X,Y).
X = ‖,
Y = 8214.

Could be a new trend, using Unicode. JCR does also something with Unicode here Logic Programming for Theory Representation and Scientific Inference in Psychology .

First, thank you for that link to the draft of the ISO appendix. I had seen it before but it completely slipped my mind. In the absence of anything else, the SWIP manual should link to it. (Maybe even capture it before it disappears.)

For operators, I would prefer to stick to characters which you commonly find on pretty much any keyboard/OS combination. I think it’s all about convenience - reading and writing. That said Unicode does open up a whole new world of possibilities.

It would be really great if we would use more than just ASCII for programming. It is of course possible, but input is a real pain in the neck. Which is actually stupid: Chinese have been using 2- and 3-keystroke combinations for typing for decades now.

Does anyone know of a working setup for using that kind of input?

You can query the classification of characters via code_type/2:

?- between(32,127,C), code_type(C,prolog_symbol), 
char_code(D,C), write(D), write(' '), fail; nl.
# $ & * + - . / : < = > ? @ \ ^ ~

But I didn’t find a class prolog_solo, so I tried this:

?- between(32,127,C), \+code_type(C,prolog_symbol), 
\+code_type(C,prolog_atom_start), \+code_type(C,prolog_var_start), 
char_code(D,C), write(D), write(' '), fail; nl.
  ! " % ' ( ) , ; [ ] ` { | }  

The vertical bar is among the above characters.

There are a lot of OS utilities around for input. Something that is directly related to Prolog is the ISO core standard which provides escaped character codes. So if all else fails, you can do in the console, using the hex representation of a Unicode character code:

?- X = '\x2200\'.
X = ∀ .

You can then copy paste the character from the console. I tested this on a Mac and it did work. Not sure whether it also works on Windows. SWI-Prolog has also a charming extension not found in the ISO core standard, namely the \uXXXX escape:

?- X = '\u2200'.
X = ∀ .

You are not seriously suggesting that I write code by typing hex representations and copy-pasting the result, right? :wink:

One approach that works is to use the \LaTeX math symbols, and type the names of the symbols. So to get something like || (but actually just a double vertical line) we would type \| or \Vert. I guess most modern text editors/IDEs would provide some support for that.

Unicode is reader friendly but not currently very writer friendly which IMO limits its usefulness in operators.

But my main takeaway form all this is the somewhat idiosyncratic nature of Prolog’s unquoted atom syntax. I can perhaps understand why some of those characters are in the singleton set, but don’t really understand why | is one of those. In fact why isn’t | just a non-associative infix operator?

Anyway, it is what it is; no point in debating Prolog syntax anymore.

But a virtual keyboard that can be only reached via mouse is still quite disruptive. Didn’t figure out yet whether the Mac “Panel” OS utilitiy allows defining keyboard accelerators. Also I am not sure what JCR expects, how his system should be used, opened this ticket here.

Yes, an IDE configuration is yet another option. An OS utility is more IDE idependent, it should work for all IDEs, since it attacks the OS input method. An IDE configuration might vary from IDE to IDE, but I guess people will also do that. For example IntelliJ has something here.

I agree it is a chicken-and-egg problem, in the sense that no one seems to be doing it, so everyone assumes it is a bad idea.

There are problems, of course. I guess the biggest problem (and probably the reason why it will never catch up) is that it is difficult to tell what exactly you are looking at. Too many characters look like other characters. Exactly how long is that arrow? How close to each other are those vertical bars? and so on.

Suggestion: use and and or rather than && and ||. (This is Python-ish rather than C/Java/Javascript-ish). '/\'/2 and '\/'/2 would continue to used for bit-wise operations (and and or are “short-cut” operations which can avoid evaluating the 2nd operand).