Paul Graham's condlet without gensym for variable names
Posted: Mon Feb 21, 2011 4:26 am
Hi,
I'm relatively new to Lisp, but relatively old to computers. I'm reading through Paul Graham's On Lisp book, and I would like to ask anybody who is familiar with or can understand Paul Graham's condlet macro about his usage of gensyms there. From my point of view there's no need to use a new "gensymed" set of variables for the bindings as the variables are locally rebound by the lets the macro generates for each conditional binding. I modified the original code of condlet so that it rebinds the original variables and it looks to work without any problem. I must have overlooked something...
For those who are not familiar with the On Lisp book and condlet macro, here's an example (the book is available online for free at http://www.paulgraham.com/onlisp.html):
The condlet macro allows to evaluate a common piece of code with conditional binding.
returns (c nil)
Paul Graham's code for condlet:
The modified code without gensym:
Any help appreciated.
Vaclav
I'm relatively new to Lisp, but relatively old to computers. I'm reading through Paul Graham's On Lisp book, and I would like to ask anybody who is familiar with or can understand Paul Graham's condlet macro about his usage of gensyms there. From my point of view there's no need to use a new "gensymed" set of variables for the bindings as the variables are locally rebound by the lets the macro generates for each conditional binding. I modified the original code of condlet so that it rebinds the original variables and it looks to work without any problem. I must have overlooked something...
For those who are not familiar with the On Lisp book and condlet macro, here's an example (the book is available online for free at http://www.paulgraham.com/onlisp.html):
The condlet macro allows to evaluate a common piece of code with conditional binding.
Code: Select all
(let ((x 2))
(condlet (((= x 1)(x 'a)(y 'b))
((=x 2)(x 'c)))
(list x y))
Paul Graham's code for condlet:
Code: Select all
(defmacro condlet (clauses &body body)
(let ((body-fn (gensym))
(vars (mapcar #'(lambda (var) (cons var (gensym)))
(remove-duplicates
(mapcar #'car
(mappend #'cdr clauses))))))
`(labels ((,body-fn ,(mapcar #'car vars)
,@body))
(cond ,@(mapcar #'(lambda (clause)
(condlet-clause clause vars body-fn))
clauses)))))
(defun condlet-clause (clause vars body-fn)
`(,(car clause) (let ,(mapcar #'cdr vars)
(let ,(condlet-binds clause vars)
(,body-fn ,@(mapcar #'cdr vars))))))
(defun condlet-binds (clause vars)
(mapcar #'(lambda (bindform)
(if (consp bindform)
(cons (cdr (assoc (car bindform) vars))
(cdr bindform))))
(cdr clause)))
Code: Select all
(defmacro condlet (clauses &body body)
(let ((body-fn (gensym))
(vars (remove-duplicates
(mapcar #'car
(mappend #'cdr clauses)))))
`(labels ((,body-fn ,vars
,@body))
(cond ,@(mapcar #'(lambda (clause)
(condlet-clause clause vars body-fn))
clauses)))))
(defun condlet-clause (clause vars body-fn)
`(,(car clause) (let ,vars
(let ,(cdr clause)
(,body-fn ,@vars)))))
Vaclav