From: Kaz Kylheku
Subject: Six years makes you slightly smarter.
Date: 
Message-ID: <20081217193144.554@gmail.com>
I was just looking at a macro I wrote in 2002, and right away spotted how
the recursive macro expansion is actually a left-associative reduce.

The lower-level expander's arguments just had to be swapped.

The initial expression to the filter nicely lands a role
as the argument to REDUCE's INITIAL-VALUE.

Doh!

--- filter.lisp.orig     2008-12-02 00:01:25.000000000 -0800
+++ filter.lisp  2008-12-02 00:55:52.947889000 -0800
@@ -20,7 +20,7 @@
          (when find
            (return find)))))))

-(defun expand-filter-expr (expr input)
+(defun expand-filter-expr (input expr)
   (cond
     ((null expr)
        input)
@@ -43,9 +43,9 @@
         (t `(multiple-value-call (lambda ,(first expr)
                                    ,@(rest expr)) ,input))))
     ((eq 'lambda (first expr))
-       (expand-filter-expr (rest expr) input))
+       (expand-filter-expr input (rest expr)))
     ((eq 'function (first expr))
-       (expand-filter-expr (second expr) input))
+       (expand-filter-expr input (second expr)))
     ((member (first expr) *filter-mapping-functions*)
        (cond
         ((and (consp (second expr))
@@ -55,7 +55,7 @@
            `(,(first expr) #',(second expr) ,@(rest (rest expr)) ,input))
         (t (let ((input-sym (gensym "INPUT-")))
             `(,(first expr) (lambda (,input-sym)
-                              ,(expand-filter-expr (second expr) input-sym))
+                              ,(expand-filter-expr input-sym (second expr)))
                         ,input)))))
     ((eq 'split (first expr))
        (let ((value-list-sym (gensym "VALUE-LIST-")))
@@ -96,10 +96,7 @@
   (push sym *filter-single-value-funcs*))

 (defmacro filter (initial-expr &body filter-expr-list)
-  (if (null filter-expr-list)
-    initial-expr
-    `(filter ,(expand-filter-expr (first filter-expr-list) initial-expr)
-            ,@(rest filter-expr-list))))
+  (reduce #'expand-filter-expr filter-expr-list :initial-value initial-expr))

 (defun filter-chatter (&rest args)
   (if (= (length args) 1)