maxcountryman
maxcountryman

Reputation: 1749

Idiomatic way of finding functions in a namesspace containing specific metadata?

I'm trying to figure out the best way to troll a namespace for functions that contain a specific bit of metadata. I've come up with a solution, but it feels a little awkward and I'm not at all sure I'm going about it the right way. There's a second component to this as well: I don't just want the names of the functions, I want to find them and then execute them. Here's a snippet of what I'm doing presently:

(defn wrap-routes
  [req from-ns]
  (let [publics (ns-publics from-ns)
        routes (->>
                (keys publics)
                (map #(meta (% publics)))
                (filter #(= (:route-handler %) true))
                (map #(:name %)))
        resp (first
                (->>
                  (map #((% publics) req) routes)
                  (filter #(:status %))))]
    (or resp not-found)))

As you can see, I'm doing all sorts of gymnastics to see if my metadata is attached to any functions in a given namespace and then am doing extra work after that to get the actual function back. I'm sure there must be a better way. So my question is, how would you do this?

Upvotes: 2

Views: 82

Answers (2)

amalloy
amalloy

Reputation: 91857

(defn wrap-routes [req from-ns]
  (or (first (filter :status
                     (for [[name f] (ns-publics from-ns)
                           :when (:route-handler (meta f))]
                       (f req))))
      not-found))

Upvotes: 3

Ankur
Ankur

Reputation: 33637

You can do something like this:

(defn wrap-routes
  [req from-ns]
  (->> (ns-publics from-ns)
       (filter #(:route-handler (meta (%1 1))))
       (map #((%1 1) req))
       (filter #(:status %))
       first
       (#(or % not-found))))

Upvotes: 1

Related Questions