and-let*をelispで実装してみた。

srfi-2のand-let*がelispになかったので、実装してみました。

and-let*

  • let*みたいなもの
  • 値の束縛以外に条件式も渡せる
    • 条件式の真偽で実行を続けるかどうか決める。
    • 偽になったら、途中で実行中断nil(#f)を返す

and-let*の利用例

;;let*のように使える。
(and-let* ((x 10)
	   (y (* x x)))
  (list x y)) ; => (10 100)

;;値の束縛以外にも式を渡せる(式は評価を続けるか決める)
(and-let* ((x 10)
	   (10)
	   (y (* x x)))
  (list x y)) ; => (10 100)

;;条件式が真の時(実行は続けられる)
(and-let* ((x 10)
	   ((= x 10))
	   (y (* x x)))
  (list x y)) ; => (10 100)

;;条件式が偽の時(中断され#fが返る)
(and-let* ((x 10)
	   ((= x (* x x)))
	   (y (* x x)))
  (list x y)) ; => nil

code

(defun singlep (p)
  (and (consp p) (null (cdr p))))

(defmacro and-let* (exp &rest body)
  `(%and-let* ,exp ,body))

(defmacro %and-let* (exp body)
  (cond ((null exp) `(progn ,@body))
	((singlep (car exp))
	 `(if ,@(car exp)
	      (%and-let* ,(cdr exp)
			 ,body)))
	(t `(let (,(car exp))
	      (%and-let* ,(cdr exp)
			 ,body)))))