Numeric separator syntax: Difference between revisions
mNo edit summary |
mNo edit summary |
||
Line 26: | Line 26: | ||
[(_ . x) #'(racket:#%top . x)]) |
[(_ . x) #'(racket:#%top . x)]) |
||
1_234_567.89 |
1_234_567.89 |
||
1_234__567.89</lang> |
|||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
1234567.89 |
|||
1234567.89 |
1234567.89 |
||
</pre> |
</pre> |
||
Line 37: | Line 39: | ||
Implementation details: any token with <code>_</code> is considered an identifier in vanilla Racket. If it's not defined already, it would be unbound. We therefore can define <code>#%top</code> to control these unbound identifiers: if the token is a number after removing <code>_</code>, expand it to that number. |
Implementation details: any token with <code>_</code> is considered an identifier in vanilla Racket. If it's not defined already, it would be unbound. We therefore can define <code>#%top</code> to control these unbound identifiers: if the token is a number after removing <code>_</code>, expand it to that number. |
||
If we wish to disallow multiple consecutive separators like <code> |
If we wish to disallow multiple consecutive separators like <code>1_234__567.89</code>, we could change it easily: |
||
<lang racket>#lang racket |
<lang racket>#lang racket |
||
Line 55: | Line 57: | ||
[(_ . x) #'(racket:#%top . x)]) |
[(_ . x) #'(racket:#%top . x)]) |
||
1_234_567.89 |
|||
1_234__567.89</lang> |
1_234__567.89</lang> |
||
Revision as of 14:09, 30 August 2019
Several programming languages allow separators in numbers in order to group digits together.
- Task
- Show the numeric separator syntax and describe its specification. E.g., what separators are eligible? Can there be multiple consecutive separators? What position can a separator be in? Etc.
Racket
Vanilla Racket does not have numeric separator syntax. However, it can be defined by users. For instance:
<lang racket>#lang racket
(require syntax/parse/define
(only-in racket [#%top racket:#%top]) (for-syntax racket/string))
(define-syntax-parser #%top
[(_ . x) #:do [(define s (symbol->string (syntax-e #'x))) (define num (string->number (string-replace s "_" "")))] #:when num #`#,num] [(_ . x) #'(racket:#%top . x)])
1_234_567.89 1_234__567.89</lang>
- Output:
1234567.89 1234567.89
In the above implementation of the syntax, _
is the separator. It allows multiple consecutive separators, and allows the separator anywhere in the numeral (front, middle, and back).
Implementation details: any token with _
is considered an identifier in vanilla Racket. If it's not defined already, it would be unbound. We therefore can define #%top
to control these unbound identifiers: if the token is a number after removing _
, expand it to that number.
If we wish to disallow multiple consecutive separators like 1_234__567.89
, we could change it easily:
<lang racket>#lang racket
(require syntax/parse/define
(only-in racket [#%top racket:#%top]) (for-syntax racket/string))
(define-syntax-parser #%top
[(_ . x) #:do [(define s (symbol->string (syntax-e #'x))) (define num (string->number (string-replace s "_" "")))] #:when num (syntax-parse #'x [_ #:fail-when (string-contains? s "__") "invalid multiple consecutive separator" #`#,num])] [(_ . x) #'(racket:#%top . x)])
1_234_567.89 1_234__567.89</lang>
- Output:
1_234__567.89: invalid multiple consecutive separator in: 1_234__567.89