justinethier / cyclone

:cyclone: A brand-new compiler that allows practical application development using R7RS Scheme. We provide modern features and a stable system capable of generating fast native binaries.
http://justinethier.github.io/cyclone/
MIT License
823 stars 42 forks source link

Evaluating `1#` results in `#f`? #517

Closed jpellegrini closed 8 months ago

jpellegrini commented 9 months ago

Hello,

cyclone> 1#
#f
cyclone> 2#2
#f
cyclone> 0.#
#f

The # symbol is usually meant to indicate zeros in inexact numbers:

gosh$ (+ 12# 1#)
130.0
stklos> 4##
400.0
> 5#  ;; Gambit
50.
> 3# ;; Chez
30.0
#;1> 10# ;; Chicken
100.0
scheme@(guile-user)> 9#
$1 = 90.0
1 ]=> 55#   ;; MIT
;Value: 550.

Although, as far as I can see, this is not part of R7RS. But Cyclone seems to return false whenever there's a # in a number (I'd expect it to either signal an error (as Chibi does) or follow the same behavior of other Schemes, although really, it doesn't seem to be part of the standard anyway).

Maybe this is a small glitch in the reader? Or, if this is some Cyclone extension that I don't know, I apologize.

justinethier commented 8 months ago

This is part of older standards, for example R5RS section 6.2.4:

A numerical constant may be specified to be either exact or inexact by a prefix. The prefixes are #e for exact, and #i for inexact. An exactness prefix may appear before or after any radix prefix that is used. If the written representation of a number has no exactness prefix the constant may be either inexact or exact. It is inexact if it contains a decimal point, an exponent, or a # character in the place of a digit, otherwise it is exact.

This was changed in R7RS to remove the language regarding #:

A numerical constant can be specified to be either exact or inexact by a prefix. The prefixes are #e for exact, and #i for inexact. An exactness prefix can appear before or after any radix prefix that is used. If the written representation of a number has no exactness prefix, the constant is inexact if it contains a decimal point or an exponent. Otherwise, it is exact.

So there is no requirement to implement this behavior. But perhaps we could do better than simply returning #f.

justinethier commented 8 months ago

Right now, Cyclone's reader uses string->number internally to parse numbers and returns the result directly.

It would probably be better to raise an error instead in cases where the reader cannot parse the number, such as 1#.

jpellegrini commented 8 months ago

It would probably be better to raise an error instead in cases where the reader cannot parse the number, such as 1#.

But what about symbols that start with a number, such as 1A? Cyclone also parses these as #f, but the standard requires them to be read as symbols:

(define 1A -2) (+ 1A -3) => -5 in other Schemes

But (define 1A -2) results in Error: Invalid type: expected pair, found : #f in Cyclone.

justinethier commented 8 months ago

That's a good edge case.

Chibi has trouble with this, too:

justin@ubuntu:~$ rlwrap chibi-scheme
> (define 1A 2)
ERROR on line 1: invalid numeric syntax: #\A
> 2
> ERROR on line 1: too many ')'s
> 1A
ERROR on line 2: invalid numeric syntax: #\A
> (define |1A| 2)
> 1A
ERROR on line 4: invalid numeric syntax: #\A
> |1A|
2

Compared with Cyclone:

cyclone> (define 1A 2)
Error: Invalid type: expected pair, found : #f
cyclone> (define |1A| 2)
ok
cyclone> 1A
#f
cyclone> |1A|
2

That said, we can probably do better here.

lassik commented 8 months ago

But what about symbols that start with a number, such as 1A? Cyclone also parses these as #f, but the standard requires them to be read as symbols:

R7RS does not require that. From the grammar:

<identifier> -> <initial> <subsequent>*
| <vertical line> <symbol element>* <vertical line>
| <peculiar identifier>

<initial> -> <letter> | <special initial>
lassik commented 8 months ago

More generally, tokens starting with a digit are not reliably read as symbols in Scheme.

jpellegrini commented 8 months ago

R7RS does not require that. From the grammar:

My bad. It's usual for Scheme implementations to read those as symbols, but not required indeed! Sorry!

jpellegrini commented 8 months ago

I see that commit 334787b6d6a34a65f30ff5a2414bf0c708aaf974 fixes this! :) Cool!