I'm now making a class object with Clojure which has a method returning the object itself.
Written with Java, the object that I'd like to make is like,
class Point {
public double x;
public double y;
public Point(double x, double y) {
this.x = x;
this.y = y;
}
public Point copy() {
return new Point(this.x, this.y);
}
}
The current clojure code that I wrote is like,
(ns myclass.Point
:gen-class
:prefix "point-"
:init init
:state state
:constructors {[double double] []}
:methods [[copy [] myclass.Point]]))
(defn point-init [x y]
[[] {:x x :y y}])
(defn point-copy [this]
this)
However, I got an error as follows.
java.lang.ClassNotFoundException: myclass.Point
While I have googled about this issue, I couldn't find any answers. Does anyone know the solution for this issue?
Thank you in advance for your help.
I'm not sure it's the only way, but, in order to use the generated class type in a method signature, you can generate the class in 2 steps - though it's still in one file and compiled in one pass:
gen-class
with only the constructorsgen-class
again with state, full set of constructors and methods.I tried with various methods including forward declaration, but only the above was working eventually. I did extend your example a little bit. Note That the copy
method is not very useful as-is since Point
is immutable, but you may want to provide mutators to your class.
Full listing:
(ns points.Point)
;; generate a simple class with the constructors used in the copy method
(gen-class
:name points.Point
:init init
:constructors {[] []
[double double] []})
;; generate the full class
(gen-class
:name points.Point
:prefix pt-
:main true
:state coordinates
:init init
:constructors {[] []
[double double] []}
:methods [[distance [points.Point] double]
[copy [] points.Point]])
(defn pt-init
([] (pt-init 0 0))
([x y]
[[] {:x x :y y}]))
(defn pt-copy
"Return a copy of this point"
[this]
(points.Point. (:x (.coordinates this)) (:y (.coordinates this))))
(defn pt-distance [^points.Point this ^points.Point p]
(let [dx (- (:x (.coordinates this)) (:x (.coordinates p)))
dy (- (:y (.coordinates this)) (:y (.coordinates p)))]
(Math/sqrt (+ (* dx dx) (* dy dy)))))
(defn pt-toString [this]
(str "Point: " (.coordinates this)))
;; Testing Java constructors and method call on Point class
(import (points Point))
(defn pt-main []
(let [o (Point.)
p (points.Point. 3 4)]
(println (.toString o))
(println (.toString p))
(println (.distance o p))
(println (.distance p (.copy p)))))
In order to generate the classes, configure project.clj
with the line
:aot [points.Point]
Testing with lein
gives:
tgo$ lein clean
tgo$ lein compile
Compiling points.Point
tgo$ lein run
Point: {:x 0, :y 0}
Point: {:x 3.0, :y 4.0}
5.0
0.0