I've been programming Clojure for a little while and recently started learning Common Lisp. One of my favorite things about Clojure is the threading operator ->
, which greatly simplifies long chains of nested function calls. Naturally I wanted to have this in Common Lisp.
I found an implementation here:
(defmacro -> (x &rest args) (destructuring-bind (form &rest more) args (cond (more `(-> (-> ,x ,form) ,@more)) ((and (consp form) (or (eq (car form) 'lambda) (eq (car form) 'function))) `(funcall ,form ,x)) ((consp form) `(,(car form) ,x ,@(cdr form))) (form `(,form ,x)) (t x))))
This uses a recursive macro expansion; I've read that it's better to use iteration over recursion in CL when you can, so I wrote my own version:
(defmacro -> (x &rest forms)
(labels ((expand-form (x form)
(if (consp form)
(if (or (eq (car form) 'lambda)
(eq (car form) 'function))
`(funcall ,form ,x)
`(,(car form) ,x ,@(cdr form)))
`(,form ,x))))
(do ((forms forms (cdr forms))
(x x (expand-form x (car forms))))
((not forms) x))))
I'm relatively new to Lisp so I don't know how to judge which way is better. Any comments, suggestions?
EDIT: I knew something was fishy! You don't have to use any looping constructs at all, a plain old reduce
will cut it:
(defmacro -> (x &rest forms)
(flet ((expand-form (x form)
(cond
((atom form)
`(,form ,x))
((member (car form) '(lambda function))
`(funcall ,form ,x))
(t
`(,(car form) ,x ,@(cdr form))))))
(reduce #'expand-form forms :initial-value x)))