Hi,

I'm not sure it nicer, but anyway...

It follows a similar approach as Cedric: pass down unbox info and collect 
up constants info. However I use the form itself to carry additional 
information. YMMV. One could also put info into meta.

(derive ::let ::recursive)
(derive ::fn ::recursive)

(def call #(%2 %1))

(defn maybe
  [pred f form & args]
  (if (pred form)
    (apply f form args)
    form))

(defn update-children
  [form f & args]
  (update-in form [:children] (partial map #(apply f % args))))

(defn recursive?
  [form]
  (isa? (:op form) ::recursive))

(defn processor
  [pre-fns post-fns]
  (fn this [form]
    (let [form (reduce call form pre-fns)
          form (maybe recursive? update-children form this)]
      (reduce call form post-fns))))

(defmulti set-unbox :op)

(defmethod set-unbox :default
  [form]
  form)

(defmethod set-unbox ::recursive
  [{:as form :keys [unbox op]}]
  (update-in form [:children] (partial map #(assoc % :unbox (or unbox (= op 
::let))))))

(defmulti collect-constants :op)

(defmethod collect-constants :default
  [form]
  (assoc form :constants #{}))

(defmethod collect-constants ::constant
  [form]
  (assoc form :constants #{(:form form)}))

(defmethod collect-constants ::recursive
  [{:as form :keys [children]}]
  (assoc form :constants (reduce into #{} (map :constants children))))

((processor [set-unbox] [collect-constants]) {:op ::fn :children [{:op 
::let :children [{:op ::constant :form 1}]}]})
; => {:constants #{1}, :op :user/fn, :children ({:constants #{1}, :unbox 
false, :op :user/let, :children ({:constants #{1}, :unbox true, :op 
:user/constant, :form 1})})}

Otherwise untested.

Sincerely
Meikel

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Reply via email to