Search code examples
clojureriemann

Variable Arguments for Riemann project function


So I am working on a stream function which will sum up some metrics for several events. To do this I use the project function and it looks something like this:

(project [(func (:service event) (nth service-list 0))      
          (func (:service event) (nth service-list 1))
          (func (:service event) (nth service-list 2))]
         (..))

service-list is a argument of the surrounding function, which contain a vector of services that must be added together. func is a function that takes two arguments and returns a true/false Using the above snippet works fine, but I would like to be able to simplify it so that a vector that is larger or smaller than 3 elements would work.

So far I have this:

    (project (mapv (fn[service] (
                   `func (:service event) ~service)
                   ) service-list)))
             (..)

which I think returns a vector of functions which are unevaluated. I went with this approach once I realised that project is a macro. No idea if I am doing the right thing...


Solution

  • The problem you are facing is that you can not dynamically assemble just the arguments of a macro call. Therefore you need to dynamically assemble the whole macro call.

    You can build a clojure form and call eval on it. Take the following.

        (let [args (mapv #(list 'func (:service 'event) %) service-list)
              form (list 'project args (...))]
          (eval form))
    

    Or, you could also use the riemann.streams/project* function to use predicate functions instead of where expressions.