CommonLispの"*"みたいなマクロ
CommonLispの*みたいなかんじのを考えた。健全じゃないから使えないけど。
(let$ (assoc 'Hanako '((Taro . 28) (Saburo . 19) (Hanako . 20))) (if $_ (cdr $_) "Not Found") (print "Hanako's age : " $_))
を
(let (($_0 (assoc 'Hanako '((Taro . 28) (Saburo . 19) (Hanako . 20))))) (let (($_1 (if $_0 (cdr $_0) "Not Found"))) (let (($_2 (print "Hanako's age : " $_1))) $_2)))
例のifの中で2回$_を使っているが、そういう時プログラムがすっきりして便利だと思う。
あと、こういう使い方もできる。
(let$ (+ 1 2) (* 3 4) (+ $_0 $_1)) ; => 15
マクロ:
(use srfi-13) (define-macro (let$ . arg) (define (str n) ; (str 13) => '$_13 (string->symbol (string-concatenate (list "$_" (number->string n))))) (define ($_n n p) ; ($_n 10 '(+ ($_ 2) 3)) => '(+ ($_10 2) 3) (if (pair? p) (cons ($_n n (car p)) ($_n n (cdr p))) (if (eq? p '$_) (str n) p))) (let loop ((n 0) (a arg)) (if (null? a) (str (- n 1)) `(let ((,(str n) ,($_n (- n 1) (car a)))) ,(loop (+ n 1) (cdr a))))))
追記:
letrecで囲えばrecみたいにできた。
(letrec$ (lambda (x) (if (= x 1) 1 (* x ($_0 (- x 1))))) $_) => fact