Reputation: 1853
I am using Leiningen and Clojure and for the life of me I can't understand why Clojure makes it so difficult just to import namespaces correctly. This is the following error
This is what I have in my core.clj
file:
; namespace macro
(ns animals.core
(:require animals.animal)
(:use animals.animal)
(:import (animals.animal Dog))
(:import (animals.animal Human))
(:import (animals.animal Arthropod))
(:import (animals.animal Insect)))
; make-animals will create a vector of animal objects
(defn make-animals []
(conj []
(Dog. "Terrier" "Canis lupis familiaris")
(Human. "Human" "Homo sapiens")
(Arthropod. "Brown Recluse" "Loxosceles reclusa")
(Insect. "Fire Ant" "Solenopsis conjurata")))
; print-animals will print all the animal objects
(defn print-animals [animals]
(doseq [animal animals]
(println animal)))
; move-animals will call the move action on each animal
(defn move-animals [animals]
(doseq [animal animals]
(animals.animal/move animal)))
; entry to main program
(defn -main [& args]
(let [animals make-animals]
(do
(println "Welcome to Animals!")
(println "-------------------")
(print-animals animals))))
Then, at the REPL, I enter the following (in the src/ directory of the lein
project):
user> (require 'animals.core)
nil
user> (animals.core/-main)
ClassNotFoundException animals.core java.net.URLClassLoader$1.run (URLClassLoader.java:202)
Okay... what? Why?
For reference, here is my file animal.clj
also in the animals
directory:
(ns animals.animal)
(defprotocol Animal
"A simple protocol for animal behaviors."
(move [this] "Method to move."))
(defrecord Dog [name species]
Animal
(move [this] (str "The " (:name this) " walks on all fours.")))
(defrecord Human [name species]
Animal
(move [this] (str "The " (:name this) " walks on two legs.")))
(defrecord Arthropod [name species]
Animal
(move [this] (str "The " (:name this) " walks on eight legs.")))
(defrecord Insect [name species]
Animal
(move [this] (str "The " (:name this) " walks on six legs.")))
Upvotes: 1
Views: 564
Reputation: 84361
With your code pasted into a fresh Leiningen project, I get a different error due to a typo in -main
: (let [animals make-animals] ...)
should be (let [animals (make-animals)] ...)
. With this change, it all works fine:
user=> (require 'animals.core)
nil
user=> (animals.core/-main)
Welcome to Animals!
-------------------
#animals.animal.Dog{:name Terrier, :species Canis lupis familiaris}
#animals.animal.Human{:name Human, :species Homo sapiens}
#animals.animal.Arthropod{:name Brown Recluse, :species Loxosceles reclusa}
#animals.animal.Insect{:name Fire Ant, :species Solenopsis conjurata}
nil
Incidentally, it doesn't matter where exactly you invoke lein repl
from as long as it's somewhere inside the project directory.
I'd venture a guess that there was something the matter with your namespace when you first tried to require
it and now it won't load due to some namespace loading state in your REPL. You might want to try (require :reload 'animals.core)
and if that doesn't work, restart your REPL. (You could also paste your entire REPL interaction up to the ClassNotFoundException
somewhere if you run into it again.)
Also, about your ns
form:
You shouldn't both :require
and :use
the same namespace; :use
already :require
s it.
It's more usual to use a single :import
clause (in fact, a single clause per clause type); for example,
(:import (animals.animal Dog Human Arthropod Insect))
It's purely a matter of style in Clojure, but in ClojureScript it is in fact required by the language.
Upvotes: 2