根据The Anatomy of gen-class
中对:gen-class
的说明,我使用leiningen
来获取类文件。
leon new pinger
创建项目。cd src
和mkdir some
并在其中创建了一个Example.clj
文件。:aot [some.Example]
。:aot :all
(或project.clj
)
醇>
Example.clj如下:
(ns some.Example
(:gen-class))
(defn -toString
[this]
"Hello, World!")
然后我执行lein compile
以获取target
目录中的类。
然后,我用lein repl
执行此代码。
(-toString (some.Example.)) ; should return "Hello, World!"
但是,我收到此错误消息。
CompilerException java.lang.RuntimeException: Unable to resolve symbol:
-toString in this context, compiling:(/private/var/folders/nw/dmb7jh3d2hq89296z2gnntqm0000gn/T/form-
init7145760420048735997.clj:1:1)
.toString
运行正常。
user=> (.toString (some.Example.))
"Hello, World!"
该网站解释说,我应该从-toString
和.toString
获得相同的结果,但我只得到.toString
的正确结果。
Clojure中-toString
和.toString
之间有什么区别?为什么-toString
会在示例中引发错误?
答案 0 :(得分:7)
首先,一些术语:
(.toString (some.Example.))
是对新构建的toString
实例的some.Example
方法的调用。
(-toString (some.Example.))
是一个常规的Clojure函数调用,-toString
是存储函数的Clojure Var的名称,而(some.Example.)
是其唯一参数。
:gen-class
安排事情,以便-toString
Var支持toString
方法;也就是说,对toString
实例的some.Example
方法的任何调用都会导致对-toString
的调用。所以确实只是直接调用-toString
是等效的。
但是,在通过引用存储它的Var调用Clojure函数之前,需要确保已经加载了这个Var所在的命名空间(这里没有问题,因为你能够构造some.Example
)的实例,然后通过其完全限定名称引用Var,或者使用refer
,use
,require
或alias
来可以用更短的名称来引用它:
(some.Example/-toString ...)
(use '[some.Example :only [-toString]])
(-toString ...)
(require '[some.Example :refer [-toString]])
(-toString ...)
(require '[some.Example :as se])
(se/-toString ...)
;; refer and alias are typically not used directly
如果您在没有先使用{sup> 1 所示的-toString
,refer
或use
的情况下说require
,Clojure将尝试解析该符号-toString
到当前命名空间中的Var(在REPL会话中通常为user
;对于lein repl
,它可能是:main
表单中的defproject
命名空间。 / p>
1 那是关于REPL的。在源文件中,您通常会在:use
表单中使用:require
或ns
;语法与use
/ require
减去引号相同。