创建后缀数字 Racket [英] Create suffixed numbers Racket

查看:59
本文介绍了创建后缀数字 Racket的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在 Racket 中做些什么,我想用字母作为数字后缀.

I'm trying to experiment with what I can do in Racket, and I want to suffix numbers with letters.

在这个例子中,我只想将 10000 表示为 10K,将 1000000 表示为 1M.

For this example, I'd simply like to represent 10000 as 10K, and 1000000 as 1M.

有没有办法(使用宏或其他方式)将 1M 扩展为:

Is there way (with macros or otherwise) that I can expand 1M to:

(* 1 1000000)

或者类似的东西?

推荐答案

在 Racket 中,10K 之类的东西是 标识符,通常会引用变量.有两种方法可以将它们变成数字:

In Racket, things like 10K are identifiers, which normally would refer to variables. There are two ways to make them into numbers:

您可以通过定义 #%top 宏来重新定义对未定义标识符执行的操作.

You can redefine what to do on an undefined identifier by defining a #%top macro.

#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)])

然而,这有一个微妙的问题.如果您的程序中有任何标识符或变量以 K 结尾,则它们可以覆盖任何以这种方式编写的数字.您需要小心,不要意外覆盖原本打算作为数字的内容.

However, this has a subtle problem. If there are any identifiers or variables in your program with K's on the end, they could override any numbers that were written that way. You would need to be careful not to accidentally override something that was intended to be a number.

这将花费更多时间,但它更接近于执行此操作的正确方法",因为当变量恰好在末尾具有 K 时,它可以避免冲突.

This will take more time, but it's closer to the "right way" to do this, since it avoids conflicts when variables happen to have K's on the end.

扩展阅读器的一种更简单的方法是使用 可读.您可以创建一个扩展 readtable 的函数,如下所示:

One of the easier ways to extend the reader is with a readtable. You can make a function that extends a readtable like this:

;; 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安装路径/to/number-with-k).

To use this to define a #lang language, you need to put the reader implementation in your-language/lang/reader.rkt. Here that's number-with-k/lang/reader.rkt, where the number-with-k directory is installed as a single-collection package (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 结尾的标识符,如下所示:

The main work goes into filling in the .... holes in the extend-readtable function. For example, you can make it recognize identifiers that end with K like this:

;; 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像这样:

Once this is done, and you have the number-with-k directory installed as a package, you should be able to use #lang number-with-k like this:

#lang number-with-k racket

(+ 12K 15)
; => 12015

这篇关于创建后缀数字 Racket的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆