dtg
dtg

Reputation: 1853

Clojure and Lein namespace issues using nREPL

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

Answers (1)

Michał Marczyk
Michał Marczyk

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

Related Questions