我正在尝试在Racket中进行实验,想要给数字添加后缀。
举个例子,我想把10000
表示为10K
,而把1000000
表示为1M
。
有没有一种方法(使用宏或其他方式),可以将1M
展开为:
(* 1 1000000)
或者类似的东西?
10K
这样的东西是标识符,通常会指代变量。有两种方法可以将它们转换为数字:
#%top
宏来重新定义未定义标识符的操作。#lang racket
(require syntax/parse/define
(only-in racket [#%top old-#%top]))
(define-syntax-parser #%top
[(_ . x:id)
#:when (id-has-a-k-at-the-end? #'x)
(transform-id-into-number #'x)]
[(_ . x)
#'(old-#%top . x)])
;; Readtable -> Readtable
(define (extend-readtable orig-rt)
;; Char InputPort Any Nat Nat Nat -> Any
(define (rt-proc char in src ln col pos)
....)
...
(make-readtable orig-rt
#f 'non-terminating-macro rt-proc
...))
#lang
语言,您需要将阅读器实现放在your-language/lang/reader.rkt
中。这里是number-with-k/lang/reader.rkt
,其中number-with-k
目录作为单一集合包安装(raco pkg install path/to/number-with-k
)。
number-with-k/lang/reader.rkt
#lang racket
(provide (rename-out [-read read]
[-read-syntax read-syntax]
[-get-info get-info]))
(require syntax/readerr
syntax/module-reader)
;; Readtable -> Readtable
(define (extend-readtable orig-rt)
;; Char InputPort Any Nat Nat Nat -> Any
(define (rt-proc char in src ln col pos)
....)
...
(make-readtable orig-rt
#f 'non-terminating-macro rt-proc))
;; [X ... -> Y] -> [X ... -> Y]
(define ((wrap-reader rd) . args)
(parameterize ([current-readtable (extend-readtable (current-readtable))])
(apply rd args)))
(define-values [-read -read-syntax -get-info]
(make-meta-reader 'number-with-k
"language path"
lang-reader-module-paths
wrap-reader
wrap-reader
identity))
extend-readtable
函数中的....
空缺。例如,您可以通过以下方式使其识别以K
结尾的标识符:;; Readtable -> Readtable
(define (extend-readtable orig-rt)
;; Char InputPort Any Nat Nat Nat -> Any
(define (rt-proc char in src ln col pos)
(define v (read-syntax/recursive src in char orig-rt #f))
(cond
[(and (identifier? v) (id-has-a-k-at-the-end? v))
(transform-id-into-number v)]
[else
v]))
(make-readtable orig-rt
#f 'non-terminating-macro rt-proc))
number-with-k
目录作为一个软件包,您应该能够像这样使用#lang number-with-k
:#lang number-with-k racket
(+ 12K 15)
; => 12015
(define K 1000)
(define M 1000000)
然后用 (* 3.14 M)
来表示 3.14 百万。
正如其他人所提到的,Racket 支持科学计数法, 3.14E6
也可以表示 3.14 百万。
另一个选择是定义函数 K
, M
等等,例如:
(define (M x) (* x 1000000))
您可以随后编写以下代码
(M 3.14)
表示314万。
#%top
,你可以使用identifier-binding
来检查标识符是否已经绑定 - 如果是,则可能要跳过转换。 - default.krameridentifier-binding
检查是不足以避免问题的,因为如果标识符已经被定义,它就不会在第一时间调用#%top
。 - Alex Knauth