Numeric separator syntax: Difference between revisions

From Rosetta Code
Content added Content deleted
mNo edit summary
mNo edit summary
Line 26: Line 26:
[(_ . x) #'(racket:#%top . x)])
[(_ . x) #'(racket:#%top . x)])


1_234_567.89</lang>
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>12__34</code>, we could change it easily:
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

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? 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