Fork me on GitHub
#clojure
<
2021-10-05
>
Ben Sless19:10:16

How can I call .toArray with a typed array argument without the compiler using reflection? I'm stumped =\

Ben Sless19:10:24

@U1Z5X06NP nope

(defn to-long-array
  [^java.util.Collection coll ^longs arr]
  (.toArray coll ^"[J" arr))
is reflective

Ben Sless19:10:36

public static Object invokeStatic(final Object coll, final Object arr) {
        return Reflector.invokeInstanceMethod(coll, "toArray", new Object[] { arr });
    }

Ben Sless19:10:54

.toArray specifically is being a pain

p-himik19:10:31

What if you try [Ljava.lang.Object;?

Janet A. Carr19:10:37

or try a concrete class not an interface.

p-himik19:10:14

The regular Object array gives me this:

((ArrayList)(new ArrayList())).toArray((Object[])((IFn)const__3.getRawRoot()).invoke(PersistentVector.EMPTY));
So, no reflection. :)

p-himik19:10:41

The original line is

(.toArray ^java.util.ArrayList (java.util.ArrayList.) (to-array []))
that's why it's convoluted.

p-himik19:10:28

Oh, hold on - I'm doing a dumb.

p-himik19:10:06

> Using generics, primitive types can not be passed as type parameters

phronmophobic19:10:17

why not (long-array [1 2 3]) ?

p-himik19:10:29

So that's why one of the reasons why neither longs nor "[J" will work, if I understand that statement and the right arity of toArray correctly.

Ben Sless19:10:21

Try (make-array Long ,,,), won't work either

p-himik19:10:30

(ns x
  (:import (java.util ArrayList)))

(def ^"[Ljava.lang.Object;" la (make-array Long 0))
(def a (ArrayList.))
(.toArray ^ArrayList a la)

p-himik19:10:41

Results in

((ArrayList)const__14.getRawRoot()).toArray((Object[])const__3.getRawRoot());

Ben Sless19:10:16

hm, let's see

p-himik19:10:28

So you can't have long[] but you can have Long[].

p-himik19:10:53

But wouldn't it still be useless in Clojure, given that in run time it's still Object[]?

p-himik19:10:16

So the result of both arities of .toArray in Clojure would be exactly the same.

phronmophobic19:10:37

is there a reason not to use long-array?

p-himik19:10:54

Here's the run time type of the 1-arity of .toArray :

{:name toArray,
 :return-type java.lang.Object<>,
 :declaring-class java.util.ArrayList,
 :parameter-types [java.lang.Object<>],
 :exception-types [],
 :flags #{:public}}

Ben Sless19:10:17

@U7RJTCH6J it returns a primitive type

Ben Sless19:10:37

Right, it worked with a Long[]

p-himik19:10:00

But your second message mentions [J, which is a primitive type. :)

Ben Sless19:10:32

Well, I think 10:30 PM is enough interop for one day, thanks for the help 🙂

p-himik19:10:34

I'm pretty sure you can simply call to-array if you need boxed values. The result in Clojure will still be the same.

p-himik19:10:57

No need for interop at all. Although .toArray might be a tad more efficient, if you care about it in this particular case.

phronmophobic19:10:53

if you want [Ljava.lang.Long;, then use

> (type (into-array Long [1 2 3]))
[Ljava.lang.Long;

p-himik19:10:46

Ah, so the runtime type is different. Huh. Got confused by my outdated knowledge on type erasure.

Ben Sless05:10:11

"Damn you, type erasure"