-
Enhancement
-
Resolution: Unresolved
-
P3
-
9, 10
Signature polymorphism is a useful component of some low-level APIs, such as VarHandles.
A simple way to add signature polymorphism to an arbitrary API is to export a factory of a temporary method handle, which is then immediate invoked:
interface SomeAPI {
Object someOperation(Object... args); // boxed version
MethodHandle someOperation(); // signature polymorphic version
MethodHandle someOperationNC(); // non-curried signature polymorphic version
}
// uses:
SomeAPI x = ...;
int res1 = (int) x.someOperation(1, "two");
int res2 = (int) x.someOperation().invokeExact(1, "two");
int res3 = (int) x.someOperationNC().invokeExact(x, 1, "two");
The non-curried version avoids an internal binding operation and allows a constant MH to be returned, but is somewhat more error-prone because of the duplication of the receiver.
The curried version may run into optimization problems, since the bound MH is not a constant (although it can be a simple bindTo transform on a constant).
This RFE requests that optimizations be organized so that the res2 and res3 cases perform similarly.
The optimization will tend to help anywhere binding or currying is part of the flow of control.
(As an alternative, the API above could be endowed with the ability to emit invokedynamic instructions for the operation. In that case, there could be awkwardness associated with duplicating the receiver, but it would be hidden in the bootstrap method.)
A simple way to add signature polymorphism to an arbitrary API is to export a factory of a temporary method handle, which is then immediate invoked:
interface SomeAPI {
Object someOperation(Object... args); // boxed version
MethodHandle someOperation(); // signature polymorphic version
MethodHandle someOperationNC(); // non-curried signature polymorphic version
}
// uses:
SomeAPI x = ...;
int res1 = (int) x.someOperation(1, "two");
int res2 = (int) x.someOperation().invokeExact(1, "two");
int res3 = (int) x.someOperationNC().invokeExact(x, 1, "two");
The non-curried version avoids an internal binding operation and allows a constant MH to be returned, but is somewhat more error-prone because of the duplication of the receiver.
The curried version may run into optimization problems, since the bound MH is not a constant (although it can be a simple bindTo transform on a constant).
This RFE requests that optimizations be organized so that the res2 and res3 cases perform similarly.
The optimization will tend to help anywhere binding or currying is part of the flow of control.
(As an alternative, the API above could be endowed with the ability to emit invokedynamic instructions for the operation. In that case, there could be awkwardness associated with duplicating the receiver, but it would be hidden in the bootstrap method.)