Создать суффикс с номерами Racket - PullRequest
0 голосов
/ 29 ноября 2018

Я пытаюсь поэкспериментировать с тем, что я могу сделать в Racket, и хочу добавить суффиксы к числам с буквами.

В этом примере я просто хотел бы представить 10000 как 10Kи 1000000 как 1M.

Есть ли способ (с макросами или иным образом), который я могу расширить 1M до:

(* 1 1000000)

Или что-то на этот счет?

Ответы [ 3 ]

0 голосов
/ 29 ноября 2018

В Racket такие вещи, как 10K, являются идентификаторами , которые обычно относятся к переменным.Есть два способа превратить их в числа:

1: переопределить, что означают «неопределенные» идентификаторы

Вы можете переопределить, что делать с неопределенным идентификатором, определив макрос #%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)])

Однако, здесь есть небольшая проблема.Если в вашей программе есть какие-либо идентификаторы или переменные с K, они могут переопределить любые числа, которые были написаны таким образом.Вы должны быть осторожны, чтобы случайно не переопределить что-то, что должно было быть числом.

2: создать расширение считывателя, которое превращает их в числа вместо идентификаторов

Это займет больше времени, но это ближе к «правильному» способу сделать это, так как он позволяет избежать конфликтов, когда переменные имеют конец К.

Один из самых простых способов расширить читатель - это 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
    ...))

Чтобы использовать это для определения языка #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
0 голосов
/ 29 ноября 2018

Самое простое - определить необходимые суффиксы.

(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)

возначает 3,14 млн.

0 голосов
/ 29 ноября 2018

Ракетка уже имеет встроенную поддержку для этого, вроде , через научную запись:

1e6 ; 1000000.0 ("1M")
2e7 ; 20000000.0
...