Following the explanation about :gen-class
in The Anatomy of gen-class
, I used leiningen
to get the class files.
leon new pinger
to create a project. cd src
and mkdir some
and created a Example.clj
file in it. :aot [some.Example]
(or :aot :all
) in project.clj
. The Example.clj is as follows:
(ns some.Example
(:gen-class))
(defn -toString
[this]
"Hello, World!")
Then I executed lein compile
to get the classes in target
directory.
Then, I was executing this code with lein repl
.
(-toString (some.Example.)) ; should return "Hello, World!"
However, I got this error message.
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
works fine.
user=> (.toString (some.Example.))
"Hello, World!"
The website explains that I should get the same results from both -toString
and .toString
, but I got only correct results with .toString
.
What's the difference between -toString
and .toString
in Clojure? Why -toString
raises an error in the example?
First, some terminology:
(.toString (some.Example.))
is a call to the toString
method of the newly constructed some.Example
instance.
(-toString (some.Example.))
is a regular Clojure function call, with -toString
being the name of a Clojure Var storing a function and (some.Example.)
being its sole argument.
:gen-class
arranges things so that the -toString
Var backs the toString
method; that is, any call to the toString
method of a some.Example
instance results in a call to -toString
. So it is indeed the case that just calling -toString
directly is equivalent.
However, before you can call a Clojure function by referring to the Var in which it's stored, you need to make sure the namespace in which this Var lives has been loaded (not a problem here, given that you were able to construct an instance of some.Example
) and then either refer to the Var by its fully-qualified name, or else use refer
, use
, require
or alias
to make it possible to refer to it by a shorter name:
(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
If you say -toString
without first using refer
, use
or require
as shown above 1 , Clojure will attempt to resolve the symbol -toString
to a Var in the current namespace (typically user
in REPL sessions; with lein repl
it may be the :main
namespace from your defproject
form).
1 That's speaking about the REPL. In a source file, you'd typically use :use
or :require
in your ns
form; the syntax is the same as for use
/ require
minus the quoting.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.