3
votes

It seems like lein is unpredictable in how it recompiles code. I have a gen-class file in one directory, trying to access it in another. For example, given this gen-class:

(ns a.Target
    (:gen-class
     :state state
     :init  init
     :constructors {[String String] []}))

(defn -init
  [m1  m2]
  [[]  (atom {"A" m1 "B" m2})])

(defn -deref
  [this]
  @(.state this))

And trying to access this from another namespace, reduced to trying random variations of 1, 2,3:

(ns b.runner
    (:require [a.Target  ] :as Target) ;1
    (:import '(a Target))              ;2
)

(compile 'a.Target) ;3

It seems like there is no syntax that will recognize "Target" instead of "a.Target", so there's clearly something not correct in how I'm addressing the gen-class. This is a problem because I'm trying to access our guice-injectors using annotated provider methods, and the annotation syntax doesn't seem to accept either complete or simple class specifications:

(definterface TargetProvider (^a.Target getTarget [this] ))
=> Exception in thread "main" java.lang.UnsupportedOperationException: nth not supported on this type:

or simplified ones:

(definterface TargetProvider (^Target getTarget [this] ))
=> Can't find class java.lang.Target
1
You have a typo in your ns form: (:require [a.Target :as Target]), not (:require [a.Target ] :as Target). - omiel
What are you actually trying to achieve here? - ponzao

1 Answers

3
votes

The ns expression should be (ns b (:import a.Target)) there's no need of using :require for the class to be imported. Since ns is macro, all symbols in :require, :use and other options are not evaluated, so there's no need to quote them. With the following ns declaration your definterface expression should work.

(ns b
  (:import a.Target))

(definterface TargetProvider [^a.Target getTarget []])

(->> b.TargetProvider .getMethods seq)
;= (#<Method public abstract a.Target b.TargetProvider.getTarget()>)

EDIT

This is the code for a proxy using the TargetProvider interface defined above, which I think is what you were asking for in the comments.

Note that I also modified the declaration of the interface's getTarget method, removing the this argument, since it does not actually receive a reference of the current instance. When using proxy there is an implicitly bound this local (see here for more information).

(let [x (proxy [TargetProvider] []
          (getTarget [] (Target. "x" "y")))]
  (.getTarget x))