Arity exception in clojure

4.3k views Asked by At

I have this piece of code.

(defn get-movie [name-movie contents]
 (loop [n (count contents) contents contents]
  (let [movie (first contents)]
   (if (= (:name (first contents)) name-movie)
    (movie)
    (recur (dec n) (rest contents))))))

I have sequence of maps ({:id, :name, :price} {} {}). I need to find the map with the :name as given by me (Matching movie). When I give

(get-movie "Interstellar" contents)

where contents is

({:id 10000 :name "Interstellar" :price 1}{:id 10001 :name "Ouija" :price 2}). 

I am getting the following exception. :

clojure.lang.ArityException: Wrong number of args (0) passed to: PersistentArrayMap AFn.java:437 clojure.lang.AFn.throwArity AFn.java:35 clojure.lang.AFn.invoke C:\Users\Shalima\Documents\Textbooks\Functional Programming\Programs\Assignment5.clj:53 file.test/get-movie C:\Users\Shalima\Documents\Textbooks\Functional Programming\Programs\Assignment5.clj:77 file.test/eval6219

I have been sitting with this for sometime now and still couldnt figure out what went wrong. What am I doing wrong here ?

1

There are 1 answers

5
Alex Miller On

You are invoking movie (a map) like a function. Maps can be invoked with a key for lookup, but there is no 0-arity form. Presumably you just want to return the movie rather than invoke it (by surrounding it with parentheses).

(defn get-movie [name-movie contents]
 (loop [n (count contents) contents contents]
  (let [movie (first contents)]
   (if (= (:name (first contents)) name-movie)
    movie   ;; don't invoke
    (recur (dec n) (rest contents))))))

Not important to the question, but a simpler way to write this loop with destructuring would be:

(defn get-movie [name-movie contents]
 (loop [[{n :name :as movie} & movies] contents]
  (if (= n name-movie)
   movie   ;; don't invoke
   (recur movies))))

And if you wanted to move to higher order sequence functions and away from the lower level loop entirely you could do something like:

(defn get-movie [name-movie contents]
 (first (filter #(= name-movie (:name %)) contents)))