我正在尝试在Racket中尝试我能做什么,我想用字母后缀数字.
对于这个例子,我只想代表10000as 10K和1000000as 1M.
有没有办法(用宏或其他方式)我可以扩展1M到:
(* 1 1000000)
Run Code Online (Sandbox Code Playgroud)
或者那种效果?
在球拍之类的东西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)])
Run Code Online (Sandbox Code Playgroud)
但是,这有一个微妙的问题.如果你的程序中有任何带有K的标识符或变量,它们可以覆盖那些以这种方式写入的数字.你需要注意不要意外地覆盖一些想要成为数字的东西.
这将花费更多的时间,但它更接近"正确的方式"来做到这一点,因为它避免了变量恰好在最后有K的冲突.
扩展阅读器的一种更简单的方法是可读.你可以创建一个扩展readtable的函数,如下所示:
;; 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
...))
Run Code Online (Sandbox Code Playgroud)
要使用它来定义#lang语言,您需要将阅读器实现放入your-language/lang/reader.rkt.这就是目录作为单一集合包安装的number-with-k/lang/reader.rkt地方number-with-k(raco pkg install path/to/number-with-k).
数与-K /郎/ 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))
Run Code Online (Sandbox Code Playgroud)
主要工作是填补功能中的....漏洞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))
Run Code Online (Sandbox Code Playgroud)
完成此操作后,您将number-with-k目录作为包安装,您应该能够#lang number-with-k像这样使用:
#lang number-with-k racket
(+ 12K 15)
; => 12015
Run Code Online (Sandbox Code Playgroud)