Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

'Parameter declaration <x> should be a vector' error when running as leiningen project

Tags:

clojure

I'm learning Clojure, using "Clojure for the Brave and True". At the end of Chapter 3: A Clojure Crash Course, there's an example where we hit a randomly selected body part of a hobbit.

The code runs fine for me when I run it in a REPL. To check that I'd understood how to create and run clojure projects, I created a project by running lein new app clojure-crash-course and then edited the resulting src/clojure_crash_course/core.clj file, like so:

(ns clojure-crash-course.core
  (:gen-class))

(defn -main
  (hit asym-hobbit-body-parts))

(def asym-hobbit-body-parts [{:name "head" :size 3}
                             {:name "left-eye" :size 1}
                             {:name "left-ear" :size 1}
                             {:name "mouth" :size 1}
                             {:name "nose" :size 1}
                             {:name "neck" :size 1}
                             {:name "left-shouler" :size 3}
                             {:name "left-upper-arm" :size 3}
                             {:name "chest" :size 10}
                             {:name "back" :size 10}
                             {:name "left-foream" :size 3}
                             {:name "abdomen" :size 6}
                             {:name "left-kidney" :size 1}
                             {:name "left-hand" :size 2}
                             {:name "left-knee" :size 2}
                             {:name "left-thigh" :size 4}
                             {:name "left-lower-leg" :size 3}
                             {:name "left-achilles" :size 1}
                             {:name "left-foot" :size 2}])

(defn matching-part
  [part]
  {:name (clojure.string/replace (:name part) #"^left-" "right-")
   :size (:size part)})  

(defn symmetrize-body-parts
  [asym-body-parts]
  (reduce (fn [final-body-parts part]
              (into final-body-parts (set [part (matching-part part)])))
          []
          asym-body-parts))

(defn hit
  [asym-body-parts]
  (let [sym-body-parts (symmetrize-body-parts asym-body-parts)
        body-part-size-sum (reduce + (map :size sym-body-parts))
        target (rand body-part-size-sum)]
    (loop [[part & remaining] sym-body-parts
           accumulated-size (:size part)]
      (if (> accumulated-size target)
          part
          (recur remaining (+ accumulated-size (:size (first remaining))))))))

When I run this with lein run, I get the following error:

Exception in thread "main" java.lang.IllegalArgumentException: Parameter declaration hit should be a vector, compiling:(clojure_crash_course/core.clj:2:16)

I've copy/pasted asym-hobbit-body-parts, asym-hobbit-body-parts, asym-hobbit-body-parts and hit from my source file into the REPL and can then run (hit asym-hobbit-body-parts) fine, so I'm confident it's not a typo or similar in those functions/definitions.

I'm assuming the error is in:

(defn -main
  (hit asym-hobbit-body-parts))

I've tried googling the error message, but couldn't find anything that explained where I'd gone wrong.

What am I missing about how to use the -main function? / How Clojure projects work?

like image 615
emmagordon Avatar asked Apr 17 '16 20:04

emmagordon


1 Answers

I spotted the error whilst proof-reading my question.

I'd missed out the parameters from the -main function, it should be:

(defn -main
  []
  (hit asym-hobbit-body-parts))

Fixing that up then exposes the second error, namely that the definition of the main function needs to go at the end of the file rather than at the start. Otherwise you get this error:

Exception in thread "main" java.long.RuntimeException: Unable to resolve symbol: hit in this context, compiling:(clojure_crash_course/core.clj:6:3)

since hit (and the other functions it subsequently uses) will not be in scope when -main is called.

like image 195
emmagordon Avatar answered Nov 16 '22 03:11

emmagordon