【问题标题】:Clojure and Lein namespace issues using nREPL使用 nREPL 的 Clojure 和 Lein 命名空间问题
【发布时间】:2013-06-12 06:51:20
【问题描述】:

我有很多“乐趣”,试图理解为什么以下内容不起作用。在我的lein 项目的src 目录中启动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.")))

为什么在评估 Animal 没有错误时尝试评估 Dog 会导致运行时异常?如何正确地做到这一点?

【问题讨论】:

    标签: clojure leiningen nrepl


    【解决方案1】:

    Animal 是一个协议。协议在定义它的命名空间中有一个关联的 Var。正是通过这个 Var 来引用一个协议。

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

    【讨论】:

    • 谢谢。另外,有没有办法在不指定整个命名空间的情况下调用这些项目?例如,执行(use 'animals.animal) 然后执行(extends? Animal Dog) 似乎不起作用。
    • 显然(import [animals.animal Dog]) 成功了。语法的二元性似乎是 defrecord 编译为 Java 类的结果...
    • 是的。这就是我在答案的第二段中要说的。
    猜你喜欢
    • 2013-08-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-04
    • 2017-11-14
    • 1970-01-01
    相关资源
    最近更新 更多