Reputation: 1853
I am having lots of "fun" trying to understand why the below won't work. After starting an nREPL session in the src
directory of my lein
project, I did the following:
user> (require 'animals.core)
nil
user> (animals.core/-main)
"Welcome to Animals!"
nil
user> (require 'animals.animal)
nil
user> (extends? animals.animal/Animal animals.animal/Dog)
CompilerException java.lang.RuntimeException: No such var: animals.animal/Dog, compiling:(NO_SOURCE_PATH:1:1)
Reading the Lein tutorial, my basic understanding is that I should place my source like so:
- src/
|____ animals/
|_______ core.clj
|_______ animal.clj
Where the contents of animal below look like this:
(ns animals.animal)
(defprotocol Animal
"A protocol for animal move behavior."
(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.")))
Why would a runtime exception result from attempting to evaluate Dog
when evaluating Animal
resulted in no error? How does one go about doing this correctly?
Upvotes: 1
Views: 516
Reputation: 84331
Animal
is a protocol. A protocol has an associated Var in the namespace in which it is defined. It is through this Var that one refers to a protocol.
In contrast, Dog
is a record. Records are just classes and have no Vars corresponding to them. (Well, there are factory functions stored in Vars, but you cannot refer to the record itself through those factory functions.) Thus, to refer to a record, you need to use different syntax: animals.animal.Dog
.
Upvotes: 3