Проблемы с пространством имен Clojure и Lein при использовании nREPL

У меня много "веселья", пытаясь понять, почему ниже не будет работать. После запуска сеанса nREPL в src каталог моего lein Проект, я сделал следующее:

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)

Читая учебник Lein, я понимаю, что должен разместить свой источник так:

- src/
|____ animals/
      |_______ core.clj
      |_______ animal.clj

Где содержимое животного ниже выглядит так:

(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.")))

Почему исключение во время выполнения является результатом попытки оценить Dog при оценке Animal не привело к ошибке? Как можно поступить правильно?

1 ответ

Решение

Animal это протокол. Протокол имеет связанный Var в пространстве имен, в котором он определен. Именно через этот Var можно ссылаться на протокол.

По сравнению, Dog это запись. Записи являются просто классами и не имеют соответствующих им переменных. (Ну, есть фабричные функции, хранящиеся в Vars, но вы не можете ссылаться на саму запись через эти фабричные функции.) Таким образом, чтобы ссылаться на запись, вам нужно использовать другой синтаксис: animals.animal.Dog,

Другие вопросы по тегам