#:g1: CLでSRFI 169

Posted 2020-02-19 20:07:29 GMT

先日久々にSRFIをCommon Lispに移植してみてコピペ移植もなかなか楽しいというのを思い出してきたので、また移植してみました。

今回移植したのは、SRFI 169: Underscores in numbersです。

srfi-169の概要ですが、Python、Ruby、C#、Java 7以降ように数値の桁区切りに_を使えるようにするという拡張です。

移植について

オリジナルはリーダーの変更ですが、どうにかリードテーブルをいじる程度で動かせました。
具体的には、数字と+-をマクロ文字にしてしまって、srfi-169のリーダーで読み直すという戦略です。
隅をつつけば、どこかの挙動に影響がある可能性もありますが、まあ良いでしょう。

(setq *readtable* srfi-169:srfi-169-syntax)

'(0123 0_1_2_3 0_123 01_23 012_3 +0123 +0_123 -0123 -0_123 1_2_3/4_5_6_7 12_34/5_678 0_1_23.4_5_6 1_2_3.5e6 1_2e1_2 #b10_10_10 #o23_45_67 #d45_67_89 #xAB_CD_EF #x789_9B_C9_EF #x-2_0 #o+2_345_6)(123 123 123 123 123 123 123 -123 -123 123/4567 617/2839 123.456D0 1.235D8 12000000000000 42 80247 456789 11259375 32373459439 -32 10030)

ちなみに数値の区切りにアンダーバーを許す程度の簡易的な実装であれば、

(let ((stdrt (copy-readtable nil)))
  (defun read-underscores-in-numbers (stm chr)
    (check-type chr character)
    (check-type stm (satisfies input-stream-p))
    (unread-char chr stm)
    (let ((*readtable* stdrt))
      (let ((thing (read stm T nil T)))
        (typecase thing
          (symbol
           (read-from-string
            (remove #\_
                    (string thing))))
          (T thing))))))

(map nil (lambda (c) (set-macro-character c #'read-underscores-in-numbers T)) "+-0123456789")

(list 0123 0_1_2_3 0_123 01_23 012_3 +0123 +0_123 -0123 -0_123 (+ (- 0) -123))(123 123 123 123 123 123 123 -123 -123 -123)

程度でも実現できそうです。

導入

Ultralispに登録してみたので、

(ql-dist:install-dist "http://dist.ultralisp.org/")

してあれば、

(ql:quickload :srfi-169)

でインストール可能です。

まとめ

リードテーブルも結構柔軟なので割と色々できてしまいますが、Common LispもRacketのようにリーダーの差し替えができたら良いのになと思うことはあります。


HTML generated by 3bmd in LispWorks 7.0.0

comments powered by Disqus