Wednesday, March 25, 2009

key-if macro

I stumbled on this page and started to solve the problems, Here is solution to the ex2.

Define the macro key-if to have the form

(KEY-IF test
:THEN exp1 exp2 ...
:ELSE exp3 exp4 ...)

This does about the same thing as:

(COND (test exp exp ...)
(T else-exp else-exp ...))

Almost everything is optional in key-if except the test. Here are some legal forms and their results:

> (key-if (> 3 1) :then 'ok)
OK
> (key-if (<> (key-if (> 3 1) :else 'oops)
NIL
> (key-if (> 3 1) :then)
NIL
> (key-if (> 3 1) :else 'oops :then 'ok)
OK
> (key-if (> 3 1) :else 'oops :then (print 'hi) 'ok)
HI
OK
Solution:
(defmacro key-if (test &rest args)
(defun extract-then-else (exp)
(defun iter (exp then-list else-list flag)
(cond
((null exp) (values (nreverse then-list) (nreverse else-list)))
((eq :then (car exp)) (iter (cdr exp)
then-list
else-list t))
((eq :else (car exp)) (iter (cdr exp)
then-list
else-list nil))
(t (if (null flag)
(iter (cdr exp) then-list (cons (car exp)
else-list) flag)
(iter (cdr exp) (cons (car exp) then-list)
else-list flag)))))
(iter exp nil nil nil))
(multiple-value-bind (then else) (extract-then-else args)
`(cond (,test ,(cons 'progn then))
(t ,(cons 'progn else)))))

No comments:

Post a Comment