-
-
Notifications
You must be signed in to change notification settings - Fork 658
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[java] Generalization of @FunctionalInterface #11014
Comments
Urgh, not this again... I've made en embarrassing amount of attempts at implementing this but always ran into one problem or another. The most recent approach was this branch (which I have just updated): https://github.com/HaxeFoundation/haxe/tree/jvm_functional_interfaces_for_real Unfortunately, I don't remember what problem I ran into there. The branch doesn't add any tests, so there's a good chance that it simply doesn't work at all. |
By the way, are you sure that connect-haxe-sdk example works? I don't see how the typer would allow assigning a function type to an interface. That's actually one of the common problems we still have to address because IIRC this only works with awkward abstract workarounds. |
I have confirmed the Haxe branch does not work, I created a test case on my branch. Add and subtract work but multiply and divide throw compilation errors, stating that they got Following up on |
Yes that's what I'm saying, Haxe doesn't admit the assignment in its own unification. What I'm after on that branch is to get the generator side working. I think using
Are you sure these tests are actually run? The following does not work for the same reason as your multiply example: class Flow {
public function new() {}
}
function test(c:java.util.function.Consumer<Flow>) {}
function main() {
test(function(f:Flow) {});
}
The compiler simply doesn't allow the assignment, so unless there's some abstract magic going on this should not work even for the hardcoded types like |
Just did a deeper dive to confirm, the compile define that sets Trying to test with casting: result = test.Main.performMathOperation(cast multiply); Returns:
|
Thank you for checking, I'll look into this and commit something that allows the assignment on the Haxe side so that this easier to test. |
I've made a basic implementation to allow the assignment and also added your test case. I can confirm that this fails the same way:
I don't really know what this means yet and I don't think it's strictly related to the issue itself, but rather some native interop problem. If you have any insight, please let me know. A pure Haxe implementation of your code does now compile and run on this branch: interface MathOperation {
function perform(a:Int, b:Int):Int;
}
class Ops {
static public final add:MathOperation = (a, b) -> a + b;
static public final subtract:MathOperation = (a, b) -> a - b;
static public function performMathOperation(operation:MathOperation) {
return operation.perform(8, 4);
}
}
class Main {
static function main() {
var result = Ops.performMathOperation(Ops.add);
trace('Add: ${result}');
result = Ops.performMathOperation(Ops.subtract);
trace('Subtract: ${result}');
result = Ops.performMathOperation(multiply);
trace('Multiply: ${result}');
result = Ops.performMathOperation(function(a, b):Int {
return Std.int(a / b);
});
trace('Divide: ${result}');
}
static function multiply(a, b):Int {
return a * b;
}
}
|
Interesting, does the above "pure Haxe" example work in other target languages too? There may be an issue with my example, I'm not sure, maybe try rewriting it. |
Implemented in #11019. |
I am attempting to extern to a function which registers an event with an event handler. See below.
When I try to call
register
from my Haxe code, I get:The issue is that I want to pass a lambda in, but the Java extern expects an object implementing a functional interface.
I expected that I could resolve the issue by creating my own extern like so:
This works in basic Haxe code, however I end up with a new issue: JARs which I import with
--java-lib-extern
break when I define an abstract where Java expects an interface to be.I also considered renaming my abstract, but this would require creating and maintaining modified externs for
ItemGroupEvent
, and if I later import a JAR which expects an unmodifiedItemGroupEvent
, the problem would continue to expand.I believe the only solution here is to modify Haxe to properly interpret functional interfaces from Java code. As mentioned in this blog post and seen in this ML code, Haxe implements automatic conversion for:
java.lang.Runnable
<->() -> Void
java.util.function.Consumer
<->(value:T) -> Void
java.util.function.BiConsumer
<->(value:T, value2:U) -> Void
java.util.function.Function
<->(value:T) -> R
And notably, Consumer works exactly as intended in connect-haxe-sdk (the second argument of this function is a
java.util.function.Consumer<Flow>
).However, this only works for these SPECIFIC interfaces, and does not work for any other interfaces with
@FunctionalInterface
specified, includingjava.util.function.Supplier
,ItemGroupEvents_ModifyEntries
from the library I'm using, and [countless others](language:java @FunctionalInterface).JavaFunctionalInterfaces
should determine each functional interface's name, classpath, parameters, arguments, and return type from reading the Java classpath properly.EDIT: For the sake of tracking, here is a list of relevant issues:
java.util.function
(Functional Interfaces) do not work as in java. #10515The text was updated successfully, but these errors were encountered: