如何在clojure中使用自己的命名空间之外的类型?

Nic*_*ton 12 testing clojure deftype leiningen

我和leiningen建立了一个名为techne的项目.我创建了一个名为scrub的模块,其中包含一个名为Scrub的类型和一个名为foo的函数.

技艺/ scrub.clj:

(ns techne.scrub)
  (deftype Scrub [state]
    Object
     (toString [this]
     (str "SCRUB: " state)))

(defn foo
  [item]
  (Scrub. "foo")
  "bar")
Run Code Online (Sandbox Code Playgroud)

技艺/ scrub_test.clj:

(ns techne.scrub-test                                                                                                                                             
  (:use [techne.scrub] :reload-all)                                                                                                                               
  (:use [clojure.test]))                                                                                                                                          


(deftest test-foo                                                                                                                                                 
  (is (= "bar" (foo "foo"))))                                                                                                                                                           

(deftest test-scrub                                                                                                                                               
  (is (= (Scrub. :a) (Scrub. :a)))) 
Run Code Online (Sandbox Code Playgroud)

当我运行测试时,我收到错误:

Exception in thread "main" java.lang.IllegalArgumentException: Unable to resolve    classname: Scrub (scrub_test.clj:11)
    at clojure.lang.Compiler.analyzeSeq(Compiler.java:5376)
    at clojure.lang.Compiler.analyze(Compiler.java:5190)
    at clojure.lang.Compiler.analyzeSeq(Compiler.java:5357)
Run Code Online (Sandbox Code Playgroud)

如果我删除测试 - 擦洗一切正常.为什么:使用techne.scrub'import'函数定义而不是类型定义?如何引用类型定义?

Ale*_*ler 16

因为deftype生成一个类,所以您可能需要在ns定义中使用(:import [techne.scrub Scrub])在techne.scrub-test中导入该Java类.

我实际上在这里写了关于defrecord的同样的事情:

您可以做的另一件事是在scrub中定义构造函数:

(defn new-scrub [state] 
  (Scrub. state))
Run Code Online (Sandbox Code Playgroud)

然后你不需要在test-scrub中导入Scrub.

  • 请注意,此答案早于Clojure 1.4.从1.4开始,defrecord将自动创建位置( - > Scrub)和map(map-> Scrub)构造函数.这是首选的构造方法,只需要将这些函数引用到命名空间中 - 无需导入类. (4认同)