Reputation: 2331
I am defining a function, which takes in an array that is to be reformatted to a function. This returned function is the first argument to a filter command. The second argument is this table which I have defined
(def persons '({:id 1 :name "olleš"} {:id 2 :name "anna"} {:id 3 :name "isak"} {:id 4 :name "beatrice"}))
When I run my filter command
seminar.core=> (filter (fn [word func arg] (func word arg)) [:id > 2] persons)
I receive this error
ArityException Wrong number of args (3) passed to: core/filter clojure.lang.AFn.throwArity (AFn.java:429)
I would like my filter function to behave similarly to this one below
(filter #(< (:id %) 2) persons)
({:id 1, :name "olle"})
Upvotes: 0
Views: 183
Reputation: 29958
For simple stuff, I would just use an anonymous function:
(filter #(> (:id %) 2) persons)
=> ({:id 3, :name "isak"} {:id 4, :name "beatrice"})
Another solution is to write a predicate-generating function, instead of doing it inline.
(defn build-pred
[word func arg]
(fn [item]
(func (word item) arg)))
(filter (build-pred :id > 2) persons))
=> ({:id 3, :name "isak"} {:id 4, :name "beatrice"})
If you really want to pass in the args as a vector, just use destructuring:
(defn build-pred-vec
[[word func arg]]
(fn [item]
(func (word item) arg)))
(filter (build-pred-vec [:id > 2]) persons)
Upvotes: 1
Reputation: 295393
This is a job for partial application:
(filter
(partial
(fn [word func arg item] (func (word item) arg))
:id > 2)
persons)
Here, we create a partially applied version of the function that has word
, func
and arg
already filled in, and leave another argument -- item
-- open for the item being filtered.
Upvotes: 1