読者です 読者をやめる 読者になる 読者になる

漢数字を整数リテラルとして使えるようにする

scheme どう書く?org

漢数字で九九の表を作ってください。
ただし以下の条件をつけます。

条件
一.アラビア数字(0〜9)禁止。
  プログラムにも出力結果にもアラビア数字を含んではいけない。(全角・半角とも)
二.結果の数字は、「七」とか「一○」(=10)とか「六四」(=64)のような形式とする。
三.九九の結果をそのままプログラム中に書き込んではいけない。

http://ja.doukaku.org/212/


これ見てて、「Lispならマクロだろう」と思っていろいろやってたら、問題そのものよりも漢数字をアラビア数字と同様に整数リテラルとして使えるようにするのがゴールになってしまった。

(use srfi-1)

(define-constant *kansuuji-chars* "〇一二三四五六七八九")

(define-macro (with-kansuuji . body)
  `(begin ,@(map transform-kansuuji body)))

(define (transform-kansuuji expr)
  (cond [(kansuuji-symbol? expr)
         (kansuuji->integer expr)]
        [(pair? expr)
         (cons (transform-kansuuji (car expr))
               (transform-kansuuji (cdr expr)))]
        [else expr]))

(define (kansuuji-symbol? sym)
  (and (symbol? sym)
       (every (cut string-scan *kansuuji-chars* <>)
              (string->list (symbol->string sym)))))

(define (kansuuji->integer ks)
  (fold (lambda (c n) (+ (* 10 n) (kansuuji->integer1 c)))
        0
        (string->list (symbol->string ks))))

(define (kansuuji->integer1 k)
  (string-scan *kansuuji-chars* k))

with-kansuuji内の漢数字(のみからなるシンボル)はマクロ展開時にすべて整数に変換される。

gosh> (with-kansuuji (+ (* 一〇〇 ) (* 一〇 ) ))
365
gosh> (with-kansuuji (print ) (print ) (print ))
1
2
3
#<undef>
gosh> (with-kansuuji '一〇〇) ;; quoteしてもシンボルは返らない
100
gosh> (macroexpand '(with-kansuuji (* 一〇〇 )))
(begin (* 100 2))
gosh> 


うーん、こんなことしてる場合じゃないのに><