Rational number syntax can be extended to null, false and true?

Just notice I made a big mistake, or maybe not? I used the following
syntax for reference data type in Prolog:

reference :==  "0" "r" name .

Isn’t this in conflict to rational numbers syntax:

rational :== integer "r" integer .

Not really a rational number would have a digit after “r”, whereas
a reference data type wouldn’t have a digit after the “r”.
Now I can input output the beasts on JavaScript and Python,

and even sorting them now works:

?- sort([1,0rFalse,3.14,0rNone], L).
L = [3.14, 1, 0rNone, 0rFalse].

?- compound(0rTrue).
fail.

?- reference(0rTrue).
true.

Edit 16.03.2023
Will also bring them to Java. Although JPL proposes @(null),
@(false) and @(true)? But the advantage of the 0r syntax,
it gives a data type, which is not a compound.

Motivation to introduce these constants. JavaScript wanted
me a boolean attribute value for the attribute name “disabled”
on a DOM element. But I guess another application area

would be JSON parsing and unparsing.

When doing the “version 7 extensions” I proposed to introduce constants that are not atoms. A remain of that is the functor used for dicts:

?- functor(_{}, F, _).
F = C'dict'.

Now, while there is a write syntax, this constant cannot be read. The use case I had in mind where things like SQL NULL, JSON true/false, JavaScript undefined, etc. There was a lot of opposition against this idea and eventually it did not mature. The dict functor and the SWI-Prolog list constructor are some remains. Possibly there is renewed interest?

In part SWI-Prolog’s strings resolve this issue, using e.g., "true" and true for the string and the boolean. Downside is that, while it is typically ok to have read strings as a Prolog string, many strings in e.g. JSON are in fact values from an enumeration or other (controlled) vocabulary that you typically want as atoms.

What is a SWI Prolog string in JavaScript and what is a SWI-Prolog
atom in JavaScript? If you have SWI-Prolog inside WASM, how would
you execute this from within Prolog?

   opt = document.getElementById("foo");
   opt.disabled = true;

I have the feeling any Prolog system that has natively Booleans
and natively a Null Type has some advantage. If you have natively
Booleans, you can do something like:

    obj.disabled := <your native boolean goes here>

If you don’t have native boolean, you need some additional
conversion back and forth as some intermediary translation
step. Such intermediary translation steps get extremly

annoying when deep structures are involved. They can become
a kind of bottleneck. In WASM I think there is anyway a bottleneck
between JavaScript and SWI-Prolog WASM, since there is JSON

inbetween? Well this need not be the case? There are ways to
call more directly the JavaScript world from within WASM?

As is, true, false, null and undefined are translated to the corresponding JavaScript value. Strings are always converted to strings and atoms other than the above are translated to strings. There is, if I recall correctly, the prefix operator syntax #Term that translates any term to a JavaScript string.

That works fairly well. The main nuisance is the other way around, where any JavaScript string becomes a Prolog string while in many cases you want an atom. Some null/undefined/true/false does not help for that. Well, it would allow using atoms for all JavaScript strings. That may also have disadvantages, surely if the target Prolog has no atom-GC.

You could translate SWI-Prolog atoms to JavaScript Symbol, and
SWI-Prolog string to JavaScript String. I don’t know how this would
be done when JSON is the transport inbetween, but it is not the case

that JavaScript has only String. There is also the Symbol type:

/* JavaScript, nodeJS 19.4.0 */
> x = "abc"
'abc'
> y = Symbol(x)
Symbol(abc)
> x == y
false

/* SWI-Prolog 9.1.4 */
?- X = "abc", Y = 'abc', X == Y.
false.

But if you do that, what would be false, true and null?

How did you make this work? When I tried it, I got

?- sort([1,0rFalse,3.14,0rNone], L).
ERROR: Syntax error: Operator expected
ERROR: sort([1,
ERROR: ** here **
ERROR: 0rFalse,3.14,0rNone], L) . 

0rXXX notation:

?- sort([1,0rFalse,3.14,0rNone], L).
L = [3.14, 1, 0rNone, 0rFalse].

Its a new syntax production proposal:

rational :== integer "r" integer .
reference :==  "0" "r" name .   /* New! */

Now I already braught it to Dogelog Player and
formerly Jekejeke Prolog. But I am not so sure about it,
another solution would be to use the much hated

0’XXX notation:
0’X notation, and allow it to be followed by a name.
The example would then read:

?- sort([1,0'False,3.14,0'None], L).
L = [3.14, 1, 0'None, 0'False].

Python names versus JavaScript names:
Or maybe instead of using Python names of the constants,
could also use JavaScript names:

?- sort([1,0'false,3.14,0'null], L).
L = [3.14, 1, 0'null, 0'false].

C’XXX’ notation:
Or to use C’XXX’ notation, which is used by SWI-Prolog for
the C’dict’. But SWI-Prolog cannot yet parse it, or its parsing
is disabled, don’t know:

?- sort([1,C'false',3.14,C'null'], L).
L = [3.14, 1, C'null', C'false'].

Conceptually, that is a perfect match I guess. In practice the usage is quite different and I doubt that would make anyone happy :frowning:

Its anyway not what I am proposing, to have atoms and strings.
Or maybe you didn’t want to say that, since SWI-Prolog has atoms
and strings. What the practice usage of Symbol is I can’t tell.

Where do you derive your practice usage of Symbol from?
Its a primitive datatype in JavaScript, and you can call
Symbol.for(“key”), which will internalize the string, so that

you can use pointer equality on the result. Pretty much the same
as an atom table. What makes you think this practical use doesn’t
match a Prolog atom table? It wouldn’t match JSON usage, since

the keys are not supposed to be Symbols, only Strings. But maybe
this is only superficially, and internally they are Symbols. You could
do the same for Novacore Prolog Dicts. On the surface

Novacore Prolog Dicts would use Strings:

?- X = {"abc" : 123.45, "def": 67}.

But under the hood there would be a transition from String to Atom:

?- X = {"abc" : 123.45, "def": 67}, X =.. L.
L = [C'novacore_dict, abc, 123.45, def, 67]

The rational would be: The keys usually form a limited vocabulary.

Edit 18.03.2023
JavaScript symbols are specified here:

Symbol is a built-in object whose constructor returns a symbol primitive
Symbol - JavaScript | MDN

Interestingly with the above trick, a Prolog parser can recognize
Novacore Prolog Dicts. Since it would see this production at the
head of a Novacore Prolog Dict:

novacore_dict :== "{" string ":" term ... "}"

Which is unlike the ISO core definition of “{}”, since in
ISO core there are no strings, and even a qualified call in
ISO module assumes that we have atom “:” term. So

there would be no collision with this production:

set :== "{" term "}"

Currently I get an error when I use string keys:

/* SWI-Prolog 9.1.4 */
?- current_prolog_flag(double_quotes, X).
X = string.

?- X = _{"abc": 123.46, "def": 67}.
ERROR: Syntax error: key_expected

Also there is the annoying need for an underscore functor.

With string keys I could directly embed JSON?
In this case null, false and true could be easily an atom.
Thats kind of solving the constant problem from another angle.

But this other angle would only work inside JSON.
There is still a problem with ordinary Prolog code, and
for example the disabled setter. If we want to avoid some

bottle neck of translating structures back and forth.