Fork me on GitHub
#clojure
<
2020-12-25
>
Phil Shapiro15:12:58

I have a question about java interop with overloaded methods. I want to call LinkedList.remove(int) from clojure and I can’t seem to do it. I can only call LinkedList.remove(Object). I’ve read the Clojure docs on java interop and a few stackoverflow pages and haven’t found the solution yet.

$ clojure
Clojure 1.10.1
user=> (import (java.util LinkedList))
java.util.LinkedList
user=> (def ll (LinkedList.))
#'user/ll
user=> (.push ll "a")
nil
user=> (.push ll "b")
nil
user=> (.remove ll 0)
false
user=> (.remove ll (int 0))
false
user=> (.remove ll "b")
true
user=> 

andy.fingerhut15:12:32

I haven't discovered a way to do it in a few other minor variations using let,either. ^int type hints give errors for several variations of expressions there.

noisesmith15:12:36

yeah, I tried defining a function in order to type hint the function args, that didn't help either - I was surprised

noisesmith15:12:51

I guess it's possible with some reflection hacking, but that seems a bit much

noisesmith15:12:25

it should be possible with compile-time only reflection though(?)

thegeez15:12:40

@pshapiro try this:

(.remove ^LinkedList ll (int 0))

thegeez15:12:38

I ran your code with

(set! *warn-on-reflection* true)
which said
call to method remove can't be resolved (target class is unknown)
this is solved with hinting the target class which is
ll

👍 3
thanks2 3
Phil Shapiro16:12:58

Thanks, that’s exactly what I was looking for!

Tamas16:12:18

for the LinkedList interop before it is probably better to type hint ll on the def? If you do that you wouldn't need the cast to int ie. (remove ll 0) works. Additionally, if you don't do it then you get the same warning on (.push ll "a") ie. the Clojure compiler will fail to find the method (at compile time), because it doesn't know the type of ll. Reference: https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/Compiler.java#L1538