使用nREPL的Clojure和Lein命名空间问题

时间:2013-06-15 22:31:05

标签: clojure leiningen nrepl

我有很多“乐趣”试图理解为什么以下不起作用。在我的src项目的lein目录中启动nREPL会话后,我执行了以下操作:

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 个答案:

答案 0 :(得分:3)

Animal是一种协议。协议在命名空间中具有关联的Var,在其中定义它。通过这个Var,人们可以参考协议。

相比之下,Dog是一个记录。记录只是类,没有与之对应的Vars。 (好吧,工厂函数存储在Vars中,但是你不能通过这些工厂函数引用记录本身。)因此,要引用记录,你需要使用不同的语法:animals.animal.Dog