Proper rational numbers (prototype for testing) (Discussion)

Seeing 1/3 as a natural representation for rationals and 2020/02/01 as an odd one for dates is not a defensible argument. E.g. most paper receipts that I get use the Year/Month/Day format. Same in a lot of documents of varying origin, including legal. That said, I don’t see it as a major issue switching from 2020/02/01 to 2020-02-01. But “2020-02-01”?!? Double-quoted terms is one of the biggest f***ups in Prolog history.

I am not saying it is an odd representation. One could claim it is non-standard as the ISO 8601 defines YYYY-MM-DD. Using / is pretty common in text, but unfortunately all 6 possible field orderings occur, sometimes even in the same country. Especially together with the not uncommon YY notation this is a great recipe for missed appointments :slight_smile:

But, that is not the point. Within ASCII, there is no sensible alternative to 1/3 as confirmed by the choices made in other languages. As rationals should be primary citizens in Prolog and numbers have some importance in programming languages, I think rationals have the first right on this representation and as a result some other usages of / become impossible or require, as with -2 to -(2), a more awkward syntax such as /(2020,/(02,01)) or maybe better 2020/(02)/01 :slight_smile:

B.t.w., the proper way to represent a date in Prolog is probably date(Y,M,D). I fully agree that the operator based notation looks nice and is, as long as it is clear from the context, that this represents a date. These types of abbreviations come at a price though. A bit related to SWI-Prolog allowing for :- use_module(library(http/http_open)). as a pretty version of :- use_module(library('http/http_open')). I like using segment/segment/… for paths, but it gets ambiguous if a path segment is not an atom.

Anyway, the real question is whether or not the rational_syntax flag addresses the problem well enough for Logtalk as well as for anyone that uses int/int syntax.

1 Like

I think the same. I like most the Haskell syntax, 1%3.
Perhaps the scanner is the easier part to cope with, so… I would vote for %, it has the advantage its use could break ‘nothing more’ than comments :slight_smile: and clueless, sparse, use-once scanners

Handling that in the Prolog parser is not the biggest issue. Otherwise I fear it will break a lot more. I’ve seen enough %-comment without a space in front of it. Also editor support will get tricky. Finally, C-like languages (including Javascript) use x%y as remainder (of division).

There is so far only one example of a breakage. No doubt some more will show up. Load your program and run ?- list_rationals.. If you have no syntax errors while loading and this remains silent you are pretty safe. By default, list_rationals/0 ignores rationals as arguments of arithmetic expressions. I don’t really see how this can break anything, but using this it lists all rationals. If this stays silent, no P/Q term was re-interpreted.

?- list_rationals([arithmetic(true)]).

:slight_smile:

I would add also the yyyy-mm-dd works (mostly) seamlessly when talking to easily accessible DBs

That’s a good argument. I will make soon the necessary changes to allow YYYY-MM-DD.

As it’s in particular case in Logtalk documenting directives:

:- info([
	version is 1.0,
	author is 'Paulo Moura',
	date is 2008/3/31,
	comment is 'Ackermann function (general recursive function).'
]).

Writing instead date is date(2008,3,31) would be awkward at best.

Continuing testing the latest commits in the rational branch and also doing some comparison testing in ECLiPSe. Will report later.

2 Likes

That makes me wonder if, in alternative, 1|3 could work…

1 Like

I doubt it. ‘|’ is also used to create terms. Some people like writing [1|3] and finally, some people have a lot of trouble dealing with \, / and |. Let us not make it worse :slight_smile:

1 Like

That’s why I wrote wonder if :stuck_out_tongue:

Anyway, I just experimented starting up Logtalk using both SWI-Prolog rational branch (8.1.21-41-gfd2c60143-DIRTY) and ECLiPSe stable 7.0 #49 version.

SWI-Prolog: Logtalk loads fine with the prefer_rationals flag set to false. Fails to load with the flag set to true.

ECLiPSe: Logtalk loads fine independently of the prefer_rationals flag value (on of off). With the flag turned on, I can still do e.g.

[user 57]: X is 1/2 + 1/5.

X = 7_10
Yes (0.00s cpu)

and load Logtalk source code that uses the YYYY/MM/DD format for dates without issue and without the date being interpreted as a rational term (i.e. YYYY, MM, DD are still parsed as integers).

Needless to say, I prefer ECLiPSe behavior here :stuck_out_tongue:

1 Like

Something odd. gfd2c60143 doesn’t appear in my logs. I’m at version 8.1.21-46-gec0ff5028 :slight_smile:

Then

$ swipl
?- set_prolog_flag(rational_syntax, compatibility).
true.

?- logtalk.
<nice long header>

?- X is 1/2 + 1/5.
X = 7R10.

Instead of compatibility you can also use none. The prefer_rationals only affects arithmetic though and now means the same as its ECLiPSe cousin.

P.S. With 8.1.21-46-gec0ff5028-DIRTY I get when building:

[80/232] Building C object src/CMakeFiles/libswipl.dir/os/pl-prologflag.c.o
../src/os/pl-prologflag.c:1083:7: warning: variable 'v' is used uninitialized whenever switch default is taken [-Wsometimes-uninitialized]
      default:          assert(0);
      ^~~~~~~
../src/os/pl-prologflag.c:1086:31: note: uninitialized use occurs here
    return PL_unify_atom(val, v);
                              ^
../src/pl-ldpass.h:107:50: note: expanded from macro 'PL_unify_atom'
#define PL_unify_atom(t, a)     PL_unify_atom__LD(t, a PASS_LD)
                                                     ^
../src/os/pl-prologflag.c:1077:13: note: initialize the variable 'v' to silence this warning
  { atom_t v;
            ^
             = 0
1 warning generated.
``

Try 47 :slight_smile: I wonder whether gcc is smart enough to see that assert(0) never returns …

Unfortunately % is reserved for line comment in Prolog. I think vertical bar would work, you need to write [(1|3)] instead of [1|3] if you want a singleton with a rational number. It depends how you “fix” the token scanner and abstract tree parser.

If you fix it similar like - 42 is a negative number, you could do it in the parser and not in the scanner. Although a scanner based rational number would be more on my wishlist, in my system like in SWI-Prolog I also have -42 is

the only negative number, its also done on scanner level. I don’t think ISO core standard made - 42 mandatory, its an interpretation of the standard, and Ulrich Neumerkel was promoting the GNU variant, although

the GNU variant has some problems with term writing. A further option would be to mimic ÷ by ASCII art. Like using ./. as the operator. This is a single token in all Prolog systems I guess, similar like =.. it would be a single token.

?- op(400,yfx,./.).
true.

?- X = 1./.4, write_canonical(X), nl.
./.(1,4)
X = 1./.4.

Edit 01.02.2020:
You need a good scanner to make the later work.
The scanner must not tollerate 1. as a float number.

Think you’re missing that exactly because it’s at a different ‘syntactic level’ than terms that make it the most interesting I can think of. But of course, Jan W. takes the burden to make the whole working, and that’s the important thing in the end.

1 Like

Warnings gone :slightly_smiling_face:

I like it! A lot! But as Jan noted, it overlaps the list syntax.

About N/M, I would like to have it more for path expressions, could give a taste of object orientation to modules, at source level.

There is nothing that stops you doing so unless you want integers as path segments. Then you still need to be aware of oddities which as /aap/(dynamic)/noot.

Yes, in C++ is overridable. Then a type has a chance to implement a simple DSL that make source less cluttered.

It’s just I would prefer to see / lexicalized in path expressions (enabling OO on modules/files).

Of course, about the breakage % could introduce, I think it has an important property that make it more amenable than /, that is, the surface syntax became invalid… an easy catch, and basically doesn’t require a prolog_flag to control its behaviour.

Of course I do know the basics of path resolution in modules context, but I would like a lot to be able to write lexicalized modules/files names expressions. For instance ?- File=..., open(~/my/folder/File,...), or ?- X/Y/Z:Pred(...)..

Could be done with rewrite, and who knows, maybe in future, a pack will do.

That works fine if you define ~/ as a prefix operator. You, you cannot do this anymore

?- open(~/my/7/3).

Well, you can by examining the ratuional but then 4/2 will open 2/1 :slight_smile:

But you could already not do as below as it would open ‘~/my/2020/2/1’

?- open(~/my/2020/02/01).

Please come with existing code that breaks. Paulo did. 1/3 simply has the preference because it is what most languages do and thus we should only decide otherwise if the price is too high
or it would lead to a whole new class of inconsistencies in the syntax. As it is the same issue as with -, that is not the case. So far YYYY/MM/DD terms are the closest we got. We have also seen that in the light of standards and ambiguity this should be YYYY-MM-DD. It is up to Paulo to (1) disable rationals, (2) support them using the 1R3 syntax (which might still change) or (3) change to YYYY-MM-DD, allow users to use 1/3 and provide some tooling to quickly find and update existing code.

Note that the latter is not so hard: simply accept a term Rat/Int with an informative warning and propose a simple (not tested and may depend on the sed version)

  sed -i 's/date\s+is\s+(\d\d\d\d)/(\d\d)/(\d\d)/date is \1-\2-\3' *.lgt