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?
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.
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