Numeric separator syntax
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? 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</lang>
- Output:
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 12__34
, 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</lang>
- Output:
1_234__567.89: invalid multiple consecutive separator in: 1_234__567.89