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

0 votes
in Java Interop by

Here's an example code:

(set! *warn-on-reflection* true)
(defn hello ^String []
  "hello")
(def a (hello))
(.replace a \e \a)

;;> Reflection warning, NO_SOURCE_PATH:1:1 - call to method replace can't be resolved (target class is unknown).
;;=> "hallo"

As we can see, Clojure doesn't seem to be able to infer the type of the Var a, even though the function (hello) had its return type hinted.

It would be great if Clojure could infer this. Otherwise, as of now, the user must provide an explicit type hint for it.

1 Answer

0 votes
by

This is one of those things that seems simple but gets more complicated the longer you look at it.

Vars are inherently boxes that hold any kind of object. You can easily change the type of the held value here with:

(alter-var-root a (constantly 100))

which would make the type hint "wrong".

hello itself is a var that holds a function that has that return type. What if it's rebound before you invoke it to something with a different type hint?

Another case is multi-arity functions where different arities return objects of different types.

There are undoubtedly other things like primitives, direct linking, etc that have impacts as well.

by
Ya, I figured this was probably hard to add, though it would be nice.

I'm thinking the type hint could be added at binding time actually. When the value of the var is set, its type is known, the var meta could be updated with it. Though I reckon that might slow down def, which is already responsible for a lot of the slow startup times. Like def could grab the type of the value and update the Var meta with it.

Otherwise if done at compile time, I don't know if we need to worry about alter-var-root. That seems an edge case, and a wrong hint would just fallback on reflection no? But it seems in most cases it would be correct.

Wouldn't def be compiled when it is evaluated, so it doesn't seem possible to change the hello var in-between, or like, if the hello var changes beforehand, it doesn't matter, when we reach def it would just use whatever type hint the latest value of hello has.
...