球拍/方案将"-0"转换为"-0.0"

use*_*788 3 scheme racket

我正在编写一个简单的解释器,它应输出:+ inf或-inf用于以下计算:

(/ 0)
(/ 1 0)
(/ -0)
Run Code Online (Sandbox Code Playgroud)

我注意到0替换0给了我想要的行为.但我还没想出要转换-0-0.0. exact->inexact失去负号. (exact->inexact -0)0.0.

Ale*_*uth 5

要做到这一点,使用文字文本,-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变成完全有理数的数字.