I have a function that I basically yanked from a discussion in the Clojure google group, that takes a collection and a list of functions of arbitrary length, and filters it to return a new collection containing all elements of the original list for which at least one of the functions evaluates to true:
(defn multi-any-filter [coll & funcs]
(filter #(some true? ((apply juxt funcs) %)) coll))
I'm playing around with making a generalizable solution to Project Euler Problem 1, so I'm using it like this:
(def f3 (fn [x] (= 0 (mod x 3))))
(def f5 (fn [x] (= 0 (mod x 5))))
(reduce + (multi-any-filter (range 1 1000) f3 f5))
Which gives the correct answer.
However, I want to modify it so I can pass ints to it instead of functions, like
(reduce + (multi-any-filter (range 1 1000) 3 5))
where I can replace 3 and 5 with an arbitrary number of ints and do the function wrapping of (=0 (mod x y)) as an anonymous function inside the multi-any-filter function.
Unfortunately this is past the limit of my Clojure ability. I'm thinking that I would need to do something with map
to the list of args, but I'm not sure how to get map
to return a list of functions, each of which is waiting for another argument. Clojure doesn't seem to support currying the way I learned how to do it in other functional languages. Perhaps I need to use partial
in the right spot, but I'm not quite sure how.
In other words, I want to be able to pass an arbitrary number of arguments (that are not functions) and then have each of those arguments get wrapped in the same function, and then that list of functions gets passed to juxt
in place of funcs
in my multi-any-filter
function above.
Thanks for any tips!
(defn evenly-divisible? [x y]
(zero? (mod x y)))
(defn multi-any-filter [col & nums]
(let [partials (map #(fn [x] (evenly-divisible? x %)) nums)
f (apply juxt partials)]
(filter #(some true? (f %)) col)))
I coudn't use partial
because it applies the arg in the first position of the fn
. We want it in the second position of evenly-divisible?
We could re-arrange in evenly-divisible?
but then it would not really look correct when using it standalone.
user=> (reduce + (multi-any-filter (range 1 1000) 3 5))
233168
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With