Numeric separator syntax

From Rosetta Code
Revision as of 14:02, 30 August 2019 by rosettacode>Sorawee (Add a new task along with Racket as an example)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Numeric separator syntax is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.

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