Open jsommr opened 6 years ago
If someone can give me a few hints about where to look, perhaps I can make the appropriate changes myself :)
@nerfpops I don't find this feature to have a straightforward implementation. Here's why:
You'd have to generate additional metadata for the generated anonymous functions. Next step is figuring out how to wire the lambda callback to the equivalent of a fat arrow function declaration, and fat arrow function declaration to a kotlin lambda. Are there cases where javascript fat arrow functions should not be treated as kotlin lambdas? Should named functions be allowed as parameters? Will there be a problem if the functor (myFunc
) expects a callback with a number of parameters, but those are not handled in the javascript function? Is it possible that the functor has many overloads of different callback signatures?
@Pip3r4o Not a Kotlin-expert in any way but I'll try to answer your questions
Are there cases where javascript fat arrow functions should not be treated as kotlin lambdas? According to the documentation lambda expressions supports the following syntax:
class HTML {
fun body() { ... }
}
fun html(init: HTML.() -> Unit): HTML {
val html = HTML() // create the receiver object
html.init() // pass the receiver object to the lambda
return html
}
// Example usage
html { // lambda with receiver begins here
body() // calling a method on the receiver object
}
Using html
from javascript the same way as the example above, would look like
html(function() {
// `this` is now the class returned from html
this.body()
})
// or
html(context => {
context.body()
})
I'm sure this wouldn't be easy to implement. Could it be something that's unsupported in the start?
Are there cases where javascript fat arrow functions should not be treated as kotlin lambdas?
The only method on FunctionX is invoke. (arg1, arg2, ...) => { code }
would simply be a shorthand for new kotlin.jvm.functions.FunctionX({ invoke: (arg1, arg2, ...) => { code } })
Should named functions be allowed as parameters? Sure. I don't see why not, but I'm also not aware of the difference between passing an anonymous and named function. Or the complexity in passing a function from javascript to java.
Will there be a problem if the functor (myFunc) expects a callback with a number of parameters, but those are not handled in the javascript function? It's important to match the FunctionX signature in Kotlin, eg.
fun myfun(callback: (arg: String) -> Void)
called from javascript via
// Don't care about the string in the callback
myfun(() => console.log("invoked"))
would have to be turned into something like
new kotlin.jvm.functions.Function1({ invoke: () => { code } })
where Function1 is important, even though the javascript callback doesn't care about the returned string.
Is it possible that the functor has many overloads of different callback signatures? Kotlin doesn't support union types and doesn't support dynamic callback signatures. It needs to explicitly know what is being passed and how many arguments are required. It's 24 classes, from Function0-23, with an invoke-method.
@jsommr any ideas how add TS declaration for kotlin
?
NativeScript supports marshalling Java bytecode generated by Kotlin. But Kotlin has a way to specify that a function takes another function in a much better way than Java.
Like this:
It compiles to something like
where Function1 is a class containing an invoke method. Depending on how many args the function takes, it'll be called Function2, Function3 and so on.
Interacting with myfun from JavaScript would be done this way:
It would be so cool if NativeScript supported Kotlin-functions out of the box, so the callback wouldn't need to be wrapped in FunctionX and myfun could be run via
myfun(() => console.log("invoked"))
. This would make it easier to align with an Objective-C library, where blocks are supported.To support Kotlin, my app.gradle currently looks like this: