1

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?

1 Answer 1

3

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.

Sign up to request clarification or add additional context in comments.

3 Comments

Thank you. Also, is there a way to invoke these items without specifying the whole namespace? For example, executing (use 'animals.animal) and then executing (extends? Animal Dog) doesn't appear to work.
Apparently (import [animals.animal Dog]) did the trick. The duality of syntax seems to be result of defrecord compiling to a Java class...
Yes. That's what I meant to say in the second paragraph of the answer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.