# Proper rational numbers (prototype for testing) (Discussion)

**URL:** <https://swi-prolog.discourse.group/t/proper-rational-numbers-prototype-for-testing-discussion/3161>\
**Category:** Discussion\
**Created:** [January 31, 2020, 4:53pm UTC](https://swi-prolog.discourse.group/t/proper-rational-numbers-prototype-for-testing-discussion/3161 "2020-01-31T16:53:08Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![pmoura](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/pmoura/32/11_2.png) [@pmoura](https://swi-prolog.discourse.group/u/pmoura)\
**Post date:** [January 31, 2020, 4:53pm UTC](https://swi-prolog.discourse.group/t/proper-rational-numbers-prototype-for-testing-discussion/3161/1 "2020-01-31T16:53:08Z")

</div>

Compiling the `rational` branch results in three warnings that don’t occur with the `master` branch:

```prolog
[271/2362] Building C object src/CMakeFiles/libswipl.dir/pl-wic.c.o
../src/pl-wic.c:1529:29: warning: absolute value function 'abs' given an argument of type 'ssize_t' (aka 'long') but has parameter of type 'int' which may cause truncation of value [-Wabsolute-value]
                mpz_load_bits(fd, p, mpz, abs(hdrsize));
                                          ^
../src/pl-wic.c:1529:29: note: use function 'labs' instead
                mpz_load_bits(fd, p, mpz, abs(hdrsize));
                                          ^~~
                                          labs
../src/pl-wic.c:1554:29: warning: absolute value function 'abs' given an argument of type 'ssize_t' (aka 'long') but has parameter of type 'int' which may cause truncation of value [-Wabsolute-value]
                mpz_load_bits(fd, p, num, abs(num_hdrsize));
                                          ^
../src/pl-wic.c:1554:29: note: use function 'labs' instead
                mpz_load_bits(fd, p, num, abs(num_hdrsize));
                                          ^~~
                                          labs
../src/pl-wic.c:1557:29: warning: absolute value function 'abs' given an argument of type 'ssize_t' (aka 'long') but has parameter of type 'int' which may cause truncation of value [-Wabsolute-value]
                mpz_load_bits(fd, p, den, abs(den_hdrsize));
                                          ^
../src/pl-wic.c:1557:29: note: use function 'labs' instead
                mpz_load_bits(fd, p, den, abs(den_hdrsize));
                                          ^~~
                                          labs
3 warnings generated.

```

Logtalk fails to start with this branch. Debugging suggest a failure when returning from a predicate call (that succeeds) to the next goal in a conjunction. Something seems broken at a low level.

---

<div class="post-metadata">

**Author:** ![ridgeworks](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/ridgeworks/32/886_2.png) [@ridgeworks](https://swi-prolog.discourse.group/u/ridgeworks)\
**Post date:** [January 31, 2020, 5:35pm UTC](https://swi-prolog.discourse.group/t/proper-rational-numbers-prototype-for-testing-discussion/3161/2 "2020-01-31T17:35:06Z")

</div>

> [@Proper rational numbers (prototype for testing)](https://swi-prolog.discourse.group/t/proper-rational-numbers-prototype-for-testing/1810/1):
>
> Rational number arithmetic can become crazy big. Should we install a tripwire system to warn/error/go to float mechanism to detect such cases?

So true. For my application I convert a rational to a float whenever:  
`abs(Numerator)+(Denominator) > max_tagged_integer`

but this is a fairly conservative limit and may, in general, not be the best. It’s also important that the rounding direction be specifiable when precision is lost since I’m using a pair of numeric values as closed bounds.

Not sure what a general solution would look like, but this may be useful as a starting point.

I’m happy to do some testing if you can point me at an executable I can run on my Mac (terminal mode acceptable).

---

<div class="post-metadata">

**Author:** ![jan](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/jan/32/4_2.png) [@jan](https://swi-prolog.discourse.group/u/jan)\
**Post date:** [January 31, 2020, 7:11pm UTC](https://swi-prolog.discourse.group/t/proper-rational-numbers-prototype-for-testing-discussion/3161/4 "2020-01-31T19:11:15Z")

</div>

Thanks for the quick test! Pushed a fix for the MacOS warnings, though they will not break anything.

Looked at the Logtalk starting issue. This is a bit hard as you disabled most tracing 🙂 Anyway, with some trace/1 calls I got some idea what went wrong after verifying that work fine with

```
?- set_prolog_flag(rational, false).

```

The trouble is with the Logtalk info statement

```
date is 2016/07/12,

```

Which is then handled in `'$lgt_compile_entity_info_directive_pair'` using

```
Date = Year/Month/Day

```

Finally your `throw(type_error(date, Date))` apparently is caught before reaching the user, so this was a bit hard to find ☹

Now the question is what to learn from this? `2016/07/12` is parsed to a term /(Rat,12) where rat is the rational number following from `2016/07`, which is turned into the canonical representation `288`. This means that effectively this doesn’t work and there is no (meaningful) way to get `2016/07` from this.

There seem to be a couple of ways out

- Forget about the idea to use `3/1` as a rational and go back to one of the more exotic ways to write rational numbers.
- Do not perform canonicalization of rationals in read/1, so we can trap the rational and get the original integers to deal with notations like this. Note that this is as loss-free as the original. You can the integers, but `7` rather than `07`. This basically allows readying almost any document containing rationals as before, but you need to do some work to get back the original terms. Documents containing 2016/00 remain illegal.
- Consider that using Y/M/D for a date term is a dubious choice and insist on atoms/strings. Note that there are many [date notations](https://en.wikipedia.org/wiki/Date_format_by_country)

Note that the problem that made this hard to debug was three fold

- Disabling debugging the Logtalk core
- Logtalk loading your program by term0reading rather than compiling. After loading normal Prolog code that contains unwanted rationals, `list_rationals/0` lists possible problems.
- The Logtalk internal error getting lost somewhere.

---

<div class="post-metadata">

**Author:** ![jan](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/jan/32/4_2.png) [@jan](https://swi-prolog.discourse.group/u/jan)\
**Post date:** [January 31, 2020, 7:19pm UTC](https://swi-prolog.discourse.group/t/proper-rational-numbers-prototype-for-testing-discussion/3161/5 "2020-01-31T19:19:35Z")

</div>

> [@ridgeworks](#):
>
> So true. For my application I convert a rational to a float whenever:  
> `abs(Numerator)+(Denominator) > max_tagged_integer`
> 
> but this is a fairly conservative limit and may, in general, not be the best. It’s also important that the rounding direction be specifiable when precision is lost since I’m using a pair of numeric values as closed bounds.

The tripwire value should of course be configurable. Automatic translation to a float is rather dubious. Basically code that better used floats should be fixed by turning some constant in the computation from integer to float (in most cases) or using float/1. A tripwire can be handy to make the programmer aware and automatic translation to float could be a way make the transformation smoother.

---

<div class="post-metadata">

**Author:** ![jan](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/jan/32/4_2.png) [@jan](https://swi-prolog.discourse.group/u/jan)\
**Post date:** [January 31, 2020, 7:26pm UTC](https://swi-prolog.discourse.group/t/proper-rational-numbers-prototype-for-testing-discussion/3161/6 "2020-01-31T19:26:04Z")

</div>

> [@anon95304481](#):
>
> Can it be combined with 0b 0x prefix? In LISP something similar is possible:

Yes. The numerator and denominator can use any syntax valid for Prolog integer. The `0x` prefix of the numerator currently does not imply a `0x` for the denominator though. Seems Lisp does this. Not sure this is a good or bad idea. What about other languages?

> [@anon95304481](#):
>
> Does 1 / 2, with spaces before and after the slash, still evaluate to 0.5?

Currently not. As (violating ISO), `- 42` is a compound term in SWI-Prolog.

---

<div class="post-metadata">

**Author:** ![jan](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/jan/32/4_2.png) [@jan](https://swi-prolog.discourse.group/u/jan)\
**Post date:** [January 31, 2020, 7:34pm UTC](https://swi-prolog.discourse.group/t/proper-rational-numbers-prototype-for-testing-discussion/3161/7 "2020-01-31T19:34:58Z")

</div>

> [@ridgeworks](#):
>
> if you can point me at an executable I can run on my Mac

There are no daily executable for the Mac. It isn’t too hard to build from source though.

---

<div class="post-metadata">

**Author:** ![pmoura](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/pmoura/32/11_2.png) [@pmoura](https://swi-prolog.discourse.group/u/pmoura)\
**Post date:** [January 31, 2020, 8:09pm UTC](https://swi-prolog.discourse.group/t/proper-rational-numbers-prototype-for-testing-discussion/3161/8 "2020-01-31T20:09:55Z")

</div>

That `rational` flag is handy 🙂 Sorry that I missed it.

`2016/07/12` is a perfectly valid Prolog term and a natural representation for dates. An implementation of rational numbers should not change its meaning. Nothing Logtalk specific here.

> [@jan](#):
>
> Note that the problem that made this hard to debug was three fold
> 
> - Disabling debugging the Logtalk core
> - Logtalk loading your program by term0reading rather than compiling. After loading normal Prolog code that contains unwanted rationals, `list_rationals/0` lists possible problems.
> - The Logtalk internal error getting lost somewhere.

Debugging only _appears_ disabled in some Prolog systems. The Logtalk compiler/runtime is written in portable Prolog code (with a few bits written in Logtalk itself such as the built-in entities). Other Prolog systems don’t have any issue with debugging the code and I use their debuggers when the need arises.

I’m not sure what you mean by “rather than compiling”. True, the Logtalk compiler uses `read_term/3` to compile source files. That’s the only viable solution to cope with all the syntax differences and quirks found in every Logtalk supported Prolog system. The Logtalk compiler necessarily type checks Logtalk source code before generating intermediate Prolog code. Thus, the “unwanted rationals” already caused a type-check error before the Prolog compiler sees the intermediate code. But that’s not what hidden the issue here, as explained next.

The internal error is not lost. If a invalid date is used in the `info/1-2` directives, you get:

```plaintext
?- {loader}.
! Type error: expected integer but got a
! in directive info/1
! in file /Users/pmoura/Documents/Logtalk/logtalk3/examples/ack/ack.lgt between lines 23-28

```

But, in this case, the errors happens as soon as the first built-in entity is compiled and that is done silently as compilation errors in the built-ins entities are only an issue when a buggy or a beta build of a backend Prolog system is used (as is the case here). In particular, the code that handles printing of compiler errors and warnings was never loaded as it’s found in one of the built-in entities that is not yet loaded when the error occurs.

---

<div class="post-metadata">

**Author:** ![jan](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/jan/32/4_2.png) [@jan](https://swi-prolog.discourse.group/u/jan)\
**Post date:** [January 31, 2020, 8:48pm UTC](https://swi-prolog.discourse.group/t/proper-rational-numbers-prototype-for-testing-discussion/3161/9 "2020-01-31T20:48:47Z")

</div>

> [@pmoura](#):
>
> `rational` flag is handy 🙂 Sorry that I missed it.

The documentation isn’t very accessible yet (although apropos/1 and help/1 give the up-to-date docs). This flag may change to `prefer_rationals` as this is its ECLiPSe name. Only, in ECLiPSe is doesn’t affect the syntax as well because their `1_3` syntax is otherwise not valid Prolog. SWI-Prolog uses the underscore to allow for `1_000_000`, which is also highly appreciated by some users. So, we have a problem ☹

> [@pmoura](#):
>
> don’t have any issue with debugging the code

I haven’t really sorted out why. We had several discussions on this. Normally `'$'` predicates are locked as non-debug predicates, but using `?- set_prolog_flag(access_level, system).` re-enables debugging (with some tweaks that it starts debugging SWI-Prolog internals, so the experience is a little less human friendly). In fact this could all be relaxed. SWI-Prolog only uses `'$'` predicates in `init.pl` that is loaded into the module `system`. Anyway, that is a side topic.

So, yes, `2016/07/12` is normally a totally valid Prolog term. The issue is whether we want to sacrifice this, allowing for `1/3` as most languages that support rationals use or do we want an awkward syntax for rationals? According to @ridgeworks we have the following prior art (last line by me).

`P/Q` : Common Lisp, Python (fractions), OWL, Guile, Wolfram  
`P//Q` : Julia (also allows Q to be signed)  
`P/Qr` : Ruby  
`P_Q` : ECLiPSe

None of these work in SWI-Prolog. The `P/Qr` solution could be made to work as `P/QR` (e.g, `1/3R`), which is invalid Prolog syntax, but notable Joachim objects, claiming it is too much stress on the tokenizer to demand that much look-ahead. I don’t like it for being ugly as well as hard to handle but could live with it if it was widely used. But, it is only Ruby and then we also need to make a variation. Joachim also suggested `P_/Q`, which indeed breaks nothing, but hurts my eyes a bit :(.

So, I started to play with the idea to be brave and simply turn `1/3` into a rational. I’ve ran a lot of my Prolog programs through it and found only issues in some unit tests (e.g, using `A is 1/0` to test error handling but now `1/0` is an illegal number an load time rather than an evaluation error at run time). You found a more serious counter example. Is this a show-stopper? Or can/should we provide a work-around? Possible work-around are

- Not make the rational canonical, so the application can turn them loss-free back to a term in places where a term is expected.
- Provide an option in read\_term/3, though that would basically turn rational syntax off for Logtalk.

---

<div class="post-metadata">

**Author:** ![abramobagnara](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/abramobagnara/32/512_2.png) [@abramobagnara](https://swi-prolog.discourse.group/u/abramobagnara)\
**Post date:** [January 31, 2020, 9:25pm UTC](https://swi-prolog.discourse.group/t/proper-rational-numbers-prototype-for-testing-discussion/3161/10 "2020-01-31T21:25:13Z")

</div>

> [@jan](#):
>
> So, yes, `2016/07/12` is normally a totally valid Prolog term. The issue is whether we want to sacrifice this, allowing for `1/3` as most languages that support rationals use or do we want an awkward syntax for rationals?

IMO changing the reading interpretation of 1/3 from being a term is an huge breakage…

Consider also the difference between  
`A = 1, B = 3, C is A/B.`  
and  
`C is 1/3.`

If indeed a non-term syntax is needed for rationals I suggest we use something that currently is not a valid syntax.

---

<div class="post-metadata">

**Author:** ![ridgeworks](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/ridgeworks/32/886_2.png) [@ridgeworks](https://swi-prolog.discourse.group/u/ridgeworks)\
**Post date:** [January 31, 2020, 9:40pm UTC](https://swi-prolog.discourse.group/t/proper-rational-numbers-prototype-for-testing-discussion/3161/11 "2020-01-31T21:40:18Z")

</div>

> [@jan](#):
>
> According to @ridgeworks we have the following prior art (last line by me).
> 
> `P/Q` : Common Lisp, Python (fractions), OWL, Guile, Wolfram  
> `P//Q` : Julia (also allows Q to be signed)  
> `P/Qr` : Ruby  
> `P_Q` : ECLiPSe

For completeness: missing from my original list (see [Rational\_data\_type](https://en.wikipedia.org/wiki/Rational_data_type)):

> `PrQ` : J

Also add Smalltalk to the `P/Q` list.

---

<div class="post-metadata">

**Author:** ![ridgeworks](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/ridgeworks/32/886_2.png) [@ridgeworks](https://swi-prolog.discourse.group/u/ridgeworks)\
**Post date:** [January 31, 2020, 10:10pm UTC](https://swi-prolog.discourse.group/t/proper-rational-numbers-prototype-for-testing-discussion/3161/12 "2020-01-31T22:10:35Z")

</div>

> [@abramobagnara](#):
>
> Consider also the difference between  
> `A = 1, B = 3, C is A/B.`  
> and  
> `C is 1/3.`

Given the full proposal (Issue #539 on GitHub) there would be no difference. It’s just that `C` would be a rational number (but a `number` as opposed to `compound`) rather than a float. I’m afraid that’s the price to be paid to make rationals first class citizens. And regardless of literal syntax, division of two integers would yield a rational number (or an integer, which is a rational number).

The whole point of Jan’s exercise is to smoke out where this causes real problems, i.e., if a number was actually in rational format internally would it really break anything? He’s grepped a ton of Prolog code and hasn’t come up with anything that would be problematical, as far as I know.

One problem (in Logtalk) that has since come up is the convenience of using `/` as a date, e.g., `01/01/2020`. This happens to work fine in Prolog and is an relevant counter-argument. (I don’t think you’d be able to do this in any(?) other programming language, but they’re usually based on functions which evaluate everything.)

Given a clean slate I think `1/3` would be the right choice for a rational literal, but we don’t have that luxury. Issue #539 has a long discussion on some of the tradeoffs.

---

<div class="post-metadata">

**Author:** ![ridgeworks](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/ridgeworks/32/886_2.png) [@ridgeworks](https://swi-prolog.discourse.group/u/ridgeworks)\
**Post date:** [January 31, 2020, 10:31pm UTC](https://swi-prolog.discourse.group/t/proper-rational-numbers-prototype-for-testing-discussion/3161/13 "2020-01-31T22:31:26Z")

</div>

> [@Proper rational numbers (prototype for testing)](https://swi-prolog.discourse.group/t/proper-rational-numbers-prototype-for-testing/1810/10):
>
> Is this a show-stopper? Or can/should we provide a work-around? Possible work-around are
> 
> - Not make the rational canonical, so the application can turn them loss-free back to a term in places where a term is expected.
> - Provide an option in read\_term/3, though that would basically turn rational syntax off for Logtalk.

I can’t answer the showstopper question, but the workarounds feel a bit contrived (hard to justify). As much as I prefer the `P/Q` syntax, and in the absence of a better workaround,  
it would be better IMO to change the literal syntax.

> [@jan](#):
>
> The tripwire value should of course be configurable. Automatic translation to a float is rather dubious. Basically code that better used floats should be fixed by turning some constant in the computation from integer to float (in most cases) or using float/1. A tripwire can be handy to make the programmer aware and automatic translation to float could be a way make the transformation smoother.

Not exactly sure how this would work - maybe call a user definable hook which permits application control over when and how to convert a rational to a float?

I wouldn’t mind one of these for dealing with IEEE infinities and NaN’s as well so I wouldn’t have to put all my `is`’s in `catch`’s.

---

<div class="post-metadata">

**Author:** ![pmoura](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/pmoura/32/11_2.png) [@pmoura](https://swi-prolog.discourse.group/u/pmoura)\
**Post date:** [January 31, 2020, 10:36pm UTC](https://swi-prolog.discourse.group/t/proper-rational-numbers-prototype-for-testing-discussion/3161/14 "2020-01-31T22:36:18Z")

</div>

> [@jan](#):
>
> Thanks for the quick test! Pushed a fix for the MacOS warnings, though they will not break anything.

I can confirm that the warnings are gone. Thanks for the quick fix!

---

<div class="post-metadata">

**Author:** ![pmoura](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/pmoura/32/11_2.png) [@pmoura](https://swi-prolog.discourse.group/u/pmoura)\
**Post date:** [January 31, 2020, 10:50pm UTC](https://swi-prolog.discourse.group/t/proper-rational-numbers-prototype-for-testing-discussion/3161/15 "2020-01-31T22:50:43Z")

</div>

> [@ridgeworks](#):
>
> One problem (in Logtalk) that has since come up is the convenience of using `/` as a date, e.g., `01/01/2020` . This happens to work fine in Prolog and is an relevant counter-argument. (I don’t think you’d be able to do this in any(?) other programming language, but they’re usually based on functions which evaluate everything.)

Again, this is not a Logtalk issue. Reusing standard operators, including arithmetic operators, is a common practice to avoid the pitfalls of defining new operators. This is a perfectly valid practice as the terms that reuse the operators are used in contexts that avoid mistaken them for the original operator meaning/semantics. The canonical example is representing pairs using the `(-)/2` arithmetic operator to be able to write `Key-Value`. Converting (or attempting to convert) those terms to something else at term parsing time breaks that practice. It’s fine to interpret `A/B` as a rational term when used as a sub-term in a `is/2` goal or in an arithmetic comparison goal. Outside an arithmetic context, it breaks Prolog at a fundamental level.

---

<div class="post-metadata">

**Author:** ![ridgeworks](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/ridgeworks/32/886_2.png) [@ridgeworks](https://swi-prolog.discourse.group/u/ridgeworks)\
**Post date:** [February 1, 2020, 3:28am UTC](https://swi-prolog.discourse.group/t/proper-rational-numbers-prototype-for-testing-discussion/3161/16 "2020-02-01T03:28:12Z")

</div>

> [@pmoura](#):
>
> Again, this is not a Logtalk issue.

Totally agree that it’s not a Logtalk issue and sorry if my wording implied that. But I think it’s not quite as black and white as you state. ‘`-`’ is a prefix operator and ‘`.`’ and ‘`,`’ are infix operators, but they aren’t always interpreted as operators, e.g., when used with numbers or as a separator between list elements (or term arguments):

```
?- current_op(F,P,-), X = -2, atomic(X).
F = 200,
P = fy,
X = -2.

?- current_op(F,P,.), X = 2.0, atomic(X).
F = 100,
P = yfx,
X = 2.0.

?- current_op(F,P,,), ([X] = [a,b] ; true).
F = 1000,
P = xfy.

```

It’s always been this way, so nobody thinks about it. But this illustrates that it’s not a universally applied principle in Prolog syntax that operators are always operators. IMO using `/` for rational literals is no different, but there is a potential for conflict with prior uses, especially since `/` is an attractive character to use in different contexts, e.g., for dates.

> [@pmoura](#):
>
> It’s fine to interpret `A/B` as a rational term when used as a sub-term in a `is/2` goal or in an arithmetic comparison goal.

This is evaluation (`X is 1/2`) which is not the issue under discussion. (`is` and cousins will still see `1/N` as a compound term.) The question is given `X = 1/2`, what type is X? The objective is to find a _natural_ syntax such X is a `number`; not a `compound`.

---

<div class="post-metadata">

**Author:** ![jan](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/jan/32/4_2.png) [@jan](https://swi-prolog.discourse.group/u/jan)\
**Post date:** [February 1, 2020, 9:21am UTC](https://swi-prolog.discourse.group/t/proper-rational-numbers-prototype-for-testing-discussion/3161/17 "2020-02-01T09:21:08Z")

</div>

I tend to draw some conclusions from this.

- The single `rational` flag to both affect arithmetic and syntax is not a good idea. I’ll move the arithmetic to `prefer_rationals` to be fully compatible to ECLiPSe.
- Syntax will remain a hard debate. With @ridgeworks, I agree that handling `1/3` as rational is no different from `-2`. I’m inclined to add a flag (`rational_syntax`?) with values
  - `natural`   
 Uses `1/3`
  - `none`   
 Adds no syntax extensions for rational numbers. See below.
  - `ugly` (to be renamed)   
 Does something that is invalid syntax in Prolog. Need to think about that, but `1R3` is a good candidate.
  - `eclipse` (possibly)   
 Use `1_3` and stop making this work for digit grouping.

Using `none` may seem a weird choice, but might also not be too bad. With `prefer_rationals` to `true`, this still does

```
?- A is 1/2+1/5, atomic(A).
A = 7/10

```

But, the price is that e.g. `1/2 is 2/4` fails. Using terms 1/2, etc is fine if they end up being used in arithmetic, but not when they are used in rules/facts where they are matched against rationals.

This of course is just an ugly compromise ☹ Would it be acceptable? Then we have the default, where I’m tempted to go for `natural`, at least to give it a try. Logtalk should probably change this to something else …

Remains another open question. ECLiPSe considers rationals and integers disjoint and `3_1` is thus different from `3`. SWI-Prolog rational support always used integers as canonical rational numbers. I think this is both more efficient and natural. You would get

```
?- A is 4/2.
A = 2_1.

```

Joachim already [states](http://eclipseclp.org/wiki/Prolog/Rationals)

> **Shortcomings**  
> The strict type separation of integers and rationals may not be desirable. An alternative would be to automatically convert integral rationals (i.e. rationals with a normalized denominator of 1) to integers. SWI-Prolog does it this way already. Integers then become a subset of the rationals rather than a disjoint data type.

How do people think about that?

---

<div class="post-metadata">

**Author:** ![pmoura](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/pmoura/32/11_2.png) [@pmoura](https://swi-prolog.discourse.group/u/pmoura)\
**Post date:** [February 1, 2020, 11:23am UTC](https://swi-prolog.discourse.group/t/proper-rational-numbers-prototype-for-testing-discussion/3161/18 "2020-02-01T11:23:11Z")

</div>

> [@ridgeworks](#):
>
> It’s always been this way, so nobody thinks about it. But this illustrates that it’s not a universally applied principle in Prolog syntax that operators are always operators.

I assume you mean to write “that _characters_ are not always operators”? There are other cases of characters (or sequences of characters) declared as operators that have different meanings **depending on context**. But to reuse one of your examples, there’s no parsing ambiguity in `-2`. If we want a compound term instead of a negative integer, we need to write either `- 2` (note the space) or `'-'(2)`. The ISO standard makes this messy (`compound(- 2)` fails and `integer(- 2)` succeeds in e.g. GNU Prolog and SICStus Prolog; sigh).

> [@ridgeworks](#):
>
> IMO using `/` for rational literals is no different, but there is a potential for conflict with prior uses, especially since `/` is an attractive character to use in different contexts, e.g., for dates.

The current `rational` branch creates a conflict by changing the interpretation of a `A/B` term in **all contexts** (assuming the `rational` flag is true) from a compound term to an atomic term. That’s why I claim this (independent of context) reinterpretation breaks Prolog (operator) semantics (as ISO does in `- 2`, btw).

But, as Jan mentioned in his reply today, ECLiPSe shows that rational numbers support doesn’t necessarily cause conflicts that stop `A/B` being a compound term. For example:

```plaintext
[eclipse 44]: get_flag(prefer_rationals, Value).

Value = off
Yes (0.00s cpu)
[eclipse 45]: X = 2020/01/01.

X = 2020 / 1 / 1
Yes (0.00s cpu)
[eclipse 46]: Year/Month/Day = 2020/01/01.

Year = 2020
Month = 1
Day = 1
Yes (0.00s cpu)
[eclipse 47]: compound(2020/01/01).

Yes (0.00s cpu)
[eclipse 48]: X is 1/2 + 1/5.

X = 0.7
Yes (0.00s cpu)
[eclipse 49]: set_flag(prefer_rationals, on).

Yes (0.00s cpu)
[eclipse 50]: X = 2020/01/01.

X = 2020 / 1 / 1
Yes (0.00s cpu)
[eclipse 51]: Year/Month/Day = 2020/01/01.

Year = 2020
Month = 1
Day = 1
Yes (0.00s cpu)
[eclipse 52]: compound(2020/01/01).

Yes (0.00s cpu)
[eclipse 53]: X is 1/2 + 1/5.

X = 7_10
Yes (0.00s cpu)

```

Thus, there’s light at the end of the tunnel 🙂 Or is that a train coming? 😛

---

<div class="post-metadata">

**Author:** ![jan](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/jan/32/4_2.png) [@jan](https://swi-prolog.discourse.group/u/jan)\
**Post date:** [February 1, 2020, 11:56am UTC](https://swi-prolog.discourse.group/t/proper-rational-numbers-prototype-for-testing-discussion/3161/20 "2020-02-01T11:56:49Z")

</div>

> [@pmoura](#):
>
> But to reuse one of your examples, there’s no parsing ambiguity in `-2` . If we want a compound term instead of a negative integer, we need to write either `- 2` (note the space) or `'-'(2)` . The ISO standard makes this messy ( `compound(- 2)` fails and `integer(- 2)` succeeds in e.g. GNU Prolog and SICStus Prolog; sigh).

Nobody knew this before ISO decided that `- 2` is an integer 🙂 But, I agree with @ridgeworks and I see no difference between `-2` and `1/3` being a single token. All the same arguments wrt to being atomic or compound and arguments are precisely the same and we have been in precisely the same situation if ISO had decided that only natural numbers exist and we wanted to add negative numbers.

If long time ago the standardizers did their job and added `1/3` as a rational number (as the committees for most other language where this is an issue did), you would never have started using `date is 2020/02/01`, but e.g. `date is `2020-02-01`, which happens to work fine in this case or the more verbose but more widely used `date is “2020-02-01”`.

Pushed some more stuff that splits the flag as proposed. The `rational_syntax` flag is module sensitive and has values `natural`, `compatibility` and `none` for now. `compatibility` reads and writes rationals as e,g., `1R3`. Logtalk can simply switch to one of `compatibility` or `none` and stay happy. Users of modules can choose on per-module basis, similar to `double_quotes`, `back_quotes` and `char_escapes`.

There is still room and time to change some of this, but I think we are approaching something workable 🙂

> [@Proper rational numbers (prototype for testing)](https://swi-prolog.discourse.group/t/proper-rational-numbers-prototype-for-testing/1810/20):
>
> P÷Q

I would be in favor, but I’m afraid non-ASCII for core language syntax is still a no-go ☹

---

<div class="post-metadata">

**Author:** ![pmoura](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/pmoura/32/11_2.png) [@pmoura](https://swi-prolog.discourse.group/u/pmoura)\
**Post date:** [February 1, 2020, 12:15pm UTC](https://swi-prolog.discourse.group/t/proper-rational-numbers-prototype-for-testing-discussion/3161/21 "2020-02-01T12:15:15Z")

</div>

> [@jan](#):
>
> If long time ago the standardizers did their job and added `1/3` as a rational number (as the committees for most other language where this is an issue did), you would never have started using `date is 2020/02/01` , but e.g. `date is ` 2020-02-01 `, which happens to work fine in this case or the more verbose but more widely used ` date is “2020-02-01”`.

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.

---

<div class="post-metadata">

**Author:** ![jan](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/jan/32/4_2.png) [@jan](https://swi-prolog.discourse.group/u/jan)\
**Post date:** [February 1, 2020, 1:52pm UTC](https://swi-prolog.discourse.group/t/proper-rational-numbers-prototype-for-testing-discussion/3161/22 "2020-02-01T13:52:08Z")

</div>

> [@pmoura](#):
>
> `2020/02/01` as an _odd_ one for dates is not a defensible argument

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 🙂

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` 🙂

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.

[Next page](https://swi-prolog.discourse.group/t/proper-rational-numbers-prototype-for-testing-discussion/3161.md?page=2)
