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