I am trying to do this:
private static final VarHandle BYTE_ARRAY_LONG_VIEW =
MethodHandles.byteArrayViewVarHandle(long[].class, ByteOrder.BIG_ENDIAN);
static long longFromBytes(byte[] digest, int offset) {
return (long) BYTE_ARRAY_LONG_VIEW.get(digest, offset);
}
The issue is the polymorphic nature of .get so I am trying to use param tags but it doesn’t seem to work?Could you please be more clear?
By "trying to do this", do you mean you're trying to replicate the same code but in Clojure?
What's VarHandle - java.lang.invoke.VarHandle or something else?
If it is, what do you mean by "polymorphic nature"? There's only one .get method.
yeah same code but in clojure?
Given MethodHandles.byteArrayViewVarHandle, the package is probably java.lang.invoke, right.
And I assume you do want to call .get from Clojure.
The problem is that .get is a varargs method. You gotta construct an object array.
no I tried that
(println (long (^[Object/1] VarHandle/.get vh (object-array [ba (int 0)])))) Execution error (WrongMethodTypeException) at java.lang.invoke.MethodHandle/asTypeUncached (MethodHandle.java:915). cannot convert MethodHandle(VarHandle,byte[],int)long to (VarHandle,Object[])Object
(println (long (^[Object/1] VarHandle/.get vh (object-array [ba (int 0)]))))
Execution error (WrongMethodTypeException) at java.lang.invoke.MethodHandle/asTypeUncached (MethodHandle.java:915).
cannot convert MethodHandle(VarHandle,byte[],int)long to (VarHandle,Object[])Object
it’s kinda weird, the get method expects object array, but when you try to use it, it expects something else
here’s a full example
(import (java.lang.invoke MethodHandles VarHandle) (java.nio ByteOrder))
=> java.nio.ByteOrder
(def vh (MethodHandles/byteArrayViewVarHandle (class (long-array 0)) ByteOrder/BIG_ENDIAN))
=> #'memento.filecache.bloom/vh
(def ba (byte-array [1 2 3 4 5 6 7 8]))
=> #'memento.filecache.bloom/ba
(println (long (^[byte/1 int] VarHandle/.get vh ba (int 0))))
Syntax error (IllegalArgumentException) compiling VarHandle/.get at (/private/var/folders/fm/5mzhclpd7mj0tzjjq796ftc00000gn/T/form-init3541479456779296948.clj:1:16).
Error - param-tags [byte/1 int] insufficient to resolve method get in class java.lang.invoke.VarHandle
(println (long (^[Object/1] VarHandle/.get vh (object-array [ba (int 0)]))))
Execution error (WrongMethodTypeException) at java.lang.invoke.MethodHandle/asTypeUncached (MethodHandle.java:915).
cannot convert MethodHandle(VarHandle,byte[],int)long to (VarHandle,Object[])Objectkinda bizarre
this method is signature polymorphic, you cannot call that from clojure
Huh, alright, never even heard about those.
From https://clojure.atlassian.net/browse/CLJ-2921:
> A workaround from Clojure is to instead call invokeWithArguments and package the arguments into a list. This call is inexact and probably slower (as it does more work and requires more arg packaging) than invokeExact would be.
yeah that kinda ruins the whole point
Yeah, this is a frustrating gap right now, I have a ticket for this. We should be able to detect these methods and do the right thing in the compiler
Yeah this also relates to boxing and other topics, a lot of these paths make sense performance wise if you can pass these primitives, as soon as you need to wrap things in object array etc they become inappropriate for hot paths
Yep, I understand
you may be interested in #C02EEAUHSJJ.