我正在编写一个简单的解释器,它应输出:+ inf或-inf用于以下计算:
(/ 0)
(/ 1 0)
(/ -0)
Run Code Online (Sandbox Code Playgroud)
我注意到0替换0给了我想要的行为.但我还没想出要转换-0成-0.0.
exact->inexact失去负号.
(exact->inexact -0)给0.0.
要做到这一点,使用文字文本,-0您将不得不更改Reader,使-0读取等于-0.0,一个不精确的版本.为了保持一致,您可能希望将每个数字读作不精确的数字,无论它是否有小数点.
值得注意的是,您可以通过为数字添加前缀来执行此操作#i,例如#i-0读取等于-0.0.但是,听起来您可能想要更改阅读器,以便每个数字读取的内容都与它上面的#i前缀相同,包括-0.
扩展阅读器的一种更简单的方法是可读.你可以创建一个扩展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.这就是目录作为单一集合包安装的inexact-number/lang/reader.rkt地方inexact-number(raco pkg install path/to/inexact-number).
不精确的数/郎/ 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 'inexact-number
"language path"
lang-reader-module-paths
wrap-reader
wrap-reader
identity))
Run Code Online (Sandbox Code Playgroud)
主要工作是填补功能中的....漏洞extend-readtable.在其中rt-proc,您可以将其"窥视"到输入端口in以查看它是否为数字,如果是,则在#i附加到前面的端口上调用Racket阅读器in.您可以通过以下方式执行此操作input-port-append:
(input-port-append #f (open-input-string "#i") in)
Run Code Online (Sandbox Code Playgroud)
在上下文中extend-readtable,这里有一些代码可以进行查看和重新阅读:
;; Readtable -> Readtable
(define (extend-readtable orig-rt)
;; Char InputPort Any Nat Nat Nat -> Any
(define (rt-proc char in src ln col pos)
(define try-in (peeking-input-port in))
(define try (read/recursive try-in char orig-rt))
(cond
[(number? try)
;; read it as if it had #i on the front
(define prefix (string-append "#i" (string char)))
(define inexact-in
(input-port-append #f (open-input-string prefix) in))
(read-syntax/recursive src inexact-in #f orig-rt)]
[else
;; read normally
(read-syntax/recursive src in char orig-rt)]))
(make-readtable orig-rt
#f 'non-terminating-macro rt-proc))
Run Code Online (Sandbox Code Playgroud)
完成后,您应该能够像这样使用它:
#lang inexact-number racket
-0
; => -0.0
(/ -0)
; => -inf.0
Run Code Online (Sandbox Code Playgroud)
PS我现在已经#lang inexact-number在Racket包服务器上提供了包inexact-number-lang.顺便说一下,还有#lang exact-decimal一个相反的影响,就是把数字5.2变成完全有理数的数字.