3
votes

Sometimes I've trouble to wrap function or macros in Clojure.

For example Clojure Mongo offers a DSL to query collections: with-collection, which is a macro.

One way to use it is shown below:

(with-collection db coll
    (find {})
    (sort (array-map :score -1 :name 1)))

I'd like to create a function that receives sort function and calls with-collection.

(defn find [sort]
    (with-collection my-db my-coll
       (find {})
       sort
)

If I try to invoke that function I get the following error: ClassCastException clojure.lang.PersistentList cannot be cast to clojure.lang.IFn

(find (sort (array-map :score -1 :name 1))

I guess it's because sort is being evaluated and with-collection expects a function.

If I try to quote I get the following error: ClassCastException clojure.lang.PersistentList cannot be cast to clojure.lang.IFn

(find (quote sort (array-map :score -1 :name 1)))

If I try to pass an anonymous function I get the following error: ArityException Wrong number of args (1) passed to: main/eval139628/fn--139629

(find #(sort (array-map :score -1 :name 1))

Is it possible to wrap this kind of macro using functions? Thanks.

1
Your anonymous functions takes no arguments. Try #(sort % (array-map :score -1 :name 1))Diego Basch

1 Answers

3
votes

the thing is the with-collection macro expands to a ->, so your function should have the coll as the first parameter. Also you shadow the monger find function with your `find function. Probably you should do something like this:

(defn my-find [sort]
  (with-collection my-db my-coll
    (find {})
    sort)

and call it like this:

(my-find #(sort % (array-map :score -1 :name 1))