Welcome! Please see the About page for a little more info on how this works.

0 votes
in Java Interop by

There are cases where I have either a delay or a future returning a Java object, in those cases, it seems you can only type hint the returned value of deref from the call site.

(.reflectionAvoided ^SomeObj @some-delayed-java-object)

Is there a way to type hint it at the definition site? If not, would this be a logical feature request?

(def some-delayed-java-object
  (delay (SomeObj.)))

(.someReflectionNeedingMethod @some-delayed-java-object)

Thank You

1 Answer

+2 votes
by
edited by

Wrap it in a function that handles hinting for you. Then use that instead of a straight deref..

user> (set! *warn-on-reflection* true)
true

user> (def the-ref (delay (java.util.HashMap. )))
#'user/the-ref

user> (defn realize-map ^java.util.HashMap [some-ref]
       @some-ref)

#'user/realize-map
user> (doto (realize-map the-ref) (.put :a 2))
{:a 2}

You could generalize with protocols (or multimethods). Here's a protocol variant...

(defprotocol IMapthing
  (retrieve [this arg])
  (insert   [this k v]))

(extend-protocol IMapthing
  clojure.lang.Delay
  (retrieve [this k]   (retrieve @this k))
  (insert   [this k v] (do (insert @this k v) this))
  java.util.HashMap
  (retrieve [this k] (.get this k))
  (insert   [this k v ] (.put this k v)))

user> (def the-delay (delay (java.util.HashMap.)))
#'user/the-delay
user> (insert the-delay :a 2)
#<Delay@2ae7ca5b: {:a 2}>

user> (retrieve the-delay :a)
2

There are other schemes, but these are the least intrusive to me.

...