2011/02/08

progs

たまにはこういうのもいいでしょう。

SERIES は次のようにネストしながら、横に長くなり過ぎる。

(collect
(+ 10
(choose-if #'oddp
(scan-range :upto 5))))
;;=> (11 13 15)

そこで、パイプ的な動きをするマクロを書いてみた。ネストせず、処理の順番どおり、縦に書ける。多値には対応せず。

(progs ()
(scan-range :upto 5)
(choose-if #'oddp)
(+ 10)
(collect))
;;=> (11 13 15)

(progs (x)
(scan-range :upto 5)
(choose-if #'oddp)
(* x x)
(collect))
;;=> (1 9 25)

(progs (choose-if)
(scan-range :upto 5)
(choose-if #'oddp)
(- choose-if 10)
(collect))
;;=> (-9 -7 -5)

(progs (x)
(scan-symbols :cl)
(collect-max (length (symbol-name x)) x))
;;=> LEAST-POSITIVE-NORMALIZED-DOUBLE-FLOAT

定義はこれ。

(defun progs-body (var body)
(let ((form (if (collect (choose-if (lambda (x) (eq var x))
(scan-lists-of-lists-fringe (cdar body))))
(car body)
(append (car body) (list var)))))
(if (endp (cdr body))
form
`(let ((,var ,form))
,(progs-body var (cdr body))))))

(defmacro progs ((&optional (var (gensym))) &body body)
`(let ((,var ,(car body)))
,(progs-body var (cdr body))))

let に展開しているけど、 multiple-value-bind に展開すれば多値に対応できると思う。

0 件のコメント: