Java8 Higher-Order Functions and Kotlin Lambdas interoperability - kotlin

I have a Java example where a method is implemented as
#Override
public Function<ISeq<Item>, Double> fitness() {
return items -> {
final Item sum = items.stream().collect(Item.toSum());
return sum._size <= _knapsackSize ? sum._value : 0;
};
}
IntelliJ's automatic translation of it to Kotlin is
override fun fitness(): Function<ISeq<Item>, Double> {
return { items:ISeq<Item> ->
val sum = items.stream().collect(Item.toSum())
if (sum.size <= _knapsackSize) sum.value else 0.0
}
}
(I made the type of items explicit and changed return to 0.0)
Still I see that there are compatibility problems with Java's Function and Kotlin native lambdas, but I'm not that the most familiar with these. Error is:
Question is: is it possible to override in Kotlin the external Java library's fitness() method on this example and if so how ?

Problem:
You are returning a (Kotlin) lambda ISeq<Knapsack.Item> -> Double. But this is not what you want. You want to return a Java Function<ISeq<Knapsack.Item>, Double>.
Solution:
You can use a SAM Conversion to create a Function.
Just like Java 8, Kotlin supports SAM conversions. This means that
Kotlin function literals can be automatically converted into
implementations of Java interfaces with a single non-default method,
as long as the parameter types of the interface method match the
parameter types of the Kotlin function.
I created a minimal example to demonstrate that. Consider you have a Java class like this:
public class Foo {
public Function<String, Integer> getFunction() {
return item -> Integer.valueOf(item);
}
}
If you want to override getFunction in Kotlin you would do it like this:
class Bar: Foo() {
override fun getFunction(): Function<String, Int> {
return Function {
it.toInt()
}
}
}

When returning lambda as Java's functional interface, you have to use explicit SAM constructor:
override fun fitness(): Function<ISeq<Item>, Double> {
return Function { items:ISeq<Item> ->
val sum = items.stream().collect(Item.toSum())
if (sum.size <= _knapsackSize) sum.value else 0.0
}
}
Also don't forget to import java.util.function.Function since Kotlin has its own class of that name

Related

Simple SAM needs conversion to anonymous object

I have the following simple interface
interface A {
fun move(s:Boolean): Int
}
I have the following class
class X{
fun draw (x: A): String{
return "A"
}
fun main() {
val temp = A {
s -> 100
}
val a = draw ( { x -> 100} )
}
}
However both temp and a fail to be declared. temp complains and the suggested fix is to convert to an anonymous object as follows (which defeats the whole purpose of using a SAM?)
val temp = object : A {
override fun move(s: Boolean): Int {
return 100
}
}
a complains about a type mismatch. My question is why does this simple SAM fail? The method signature is the same.
Currently Kotlin only has SAM conversion for interfaces defined in Java.
For pure Kotlin code you're supposed to use a function type such as:
typealias A = (s: Boolean) -> Int
However, the syntax you expected will be supported in Kotlin 1.4 with interface defined as fun interface.
As announced here:
What to Expect in Kotlin 1.4 and Beyond
and tracked as KT-7770
Kotlin 1.4 has support for SAM conversions for Kotlin interfaces, in addition to the Java interface SAM conversion available in previous versions. See:
https://youtrack.jetbrains.com/issue/KT-7770
https://blog.jetbrains.com/kotlin/2019/12/what-to-expect-in-kotlin-1-4-and-beyond/#language-features
With 1.4, you do need to define your interface as a "functional" interface:
fun interface A {
fun move(s:Boolean): Int
}

Kotlin - not able to find kotin equivalent of java.util.function.Function<T, R>

I am trying to convert one of the java function which takes java.util.function.Function<T, R> to Kotlin using IDEA 2019.3 Kotlin multiplatform library.
But t I could not find a way to do an equivalent function in kotlin. I can see here that there is Function1 to do a java interoperability but I am not able to do any import from import kotlin.jvm.functions.*
I am trying Kotlin for the first time. Could someone please tell what am I doing wrong.
Update- Please see my java code
import java.util.function.Function;
public class A {
Function<String, String> function;
public A(Function<String, String> function) {
super();
this.function = function;
}
public String convert(String input) {
return function.apply(input);
}
}
Not clear about your question, but assuming you are trying to duplicate functionality from Java:
In Kotlin, you do not use Function interfaces directly because functions are first-class. The Function1, Function2, etc. classes are only used to make functions available to Java code and the JVM.
If you want to create the equivalent of a Java Function<T, R>, you would define a function using either Kotlin's fun or lambda syntax.
fun getStringLength(x: String): Int {
return x.length
}
//...
val functionReference = ::getStringLength
// Java code will treat this as a Function1<String, Int>
or
val function = fun (x: String): Int {
return x.length
}
// Java code will treat this as a Function1<String, Int>
or
val functionReference = { x: String -> x.length }
// Java code will treat this as a Function1<String, Int>
To declare that a function takes a function as a parameter, you use (input) -> output syntax as the variable type:
fun <T, R> doSomething(functionalReference: (T) -> R) {
//
}
You can call a function using its referenced name:
fun <T, R> doSomething(input: T, functionalReference: (T) -> R): R {
return functionalReference(input)
}
Sounds like you want to convert a Java function that accepts a Function to an equivalent Kotlin function.
Example:
Java
public class JavaFunctions {
public static <T,R> void runAFunction(Function<T, R> userFunction){
userFunction.apply(null);
}
}
Kotlin (These two functions are equivalent)
class KotlinFunctions{
companion object{
#JvmStatic
fun <T,R> runAFunction(userFunction:(T?) -> R?){
userFunction.invoke(null);
}
#JvmStatic
fun <T,R> runAFunction2(userFunction: Function1<T?, R?> ){
userFunction.invoke(null);
}
}
}

How to use extension functions defined in Kotlin interface

In Kotlin, it is possible to declare an extension function in an interface like this:
interface Evaluator {
fun Double.evaluateY1(): Double
fun Double.evaluateY2(): Double
}
class EvaluatorImpl : Evaluator {
override fun Double.evaluateY1(): Double {
return this + 2.0
}
override fun Double.evaluateY2(): Double {
return this + 3.0
}
}
Having a receiver and an instance of the interface, how do I invoke such extension function?
I came up with a trick involving the with scope function, but I would prefer something with less indentation.
fun usageExample(evaluator: Evaluator, x: Double) {
with(evaluator) {
println("Y1 = ${x.evaluateY1()}. Y2 = ${x.evaluateY2()}")
}
}
There's no chance to make it work without getting into the scope of your interface. Using with is the recommended solution. You can use an expression body to make it more concise:
fun usageExample(evaluator: Evaluator, x: Double) = with(evaluator) {
println("Y1 = ${x.evaluateY1()}. Y2 = ${x.evaluateY2()}")
}

Create an annotation instance in Kotlin

I have a framework written in Java that, using reflection, get the fields on an annotation and make some decisions based on them. At some point I am also able to create an ad-hoc instance of the annotation and set the fields myself. This part looks something like this:
public #interface ThirdPartyAnnotation{
String foo();
}
class MyApp{
ThirdPartyAnnotation getInstanceOfAnnotation(final String foo)
{
ThirdPartyAnnotation annotation = new ThirdPartyAnnotation()
{
#Override
public String foo()
{
return foo;
}
};
return annotation;
}
}
Now I am trying to do the exact thing in Kotlin. Bear in mind that the annotation is in a third party jar.
Anyway, here is how I tried it in Kotlin:
class MyApp{
fun getAnnotationInstance(fooString:String):ThirdPartyAnnotation{
return ThirdPartyAnnotation(){
override fun foo=fooString
}
}
But the compiler complains about: Annotation class cannot be instantiated
So the question is: how should I do this in Kotlin?
You can do this with Kotlin reflection:
val annotation = ThirdPartyAnnotation::class.constructors.first().call("fooValue")
In the case of annotation having no-arg constructor (e.g. each annotation field has a default value), you can use following approach:
annotation class SomeAnnotation(
val someField: Boolean = false,
)
val annotation = SomeAnnotation::class.createInstance()
This is the solution I might have found but feels like a hack to me and I would prefer to be able to solve it within the language.
Anyway, for what is worth,it goes like this:
class MyApp {
fun getInstanceOfAnnotation(foo: String): ThirdPartyAnnotation {
val annotationListener = object : InvocationHandler {
override fun invoke(proxy: Any?, method: Method?, args: Array<out Any>?): Any? {
return when (method?.name) {
"foo" -> foo
else -> FindBy::class.java
}
}
}
return Proxy.newProxyInstance(ThirdPartyAnnotation::class.java.classLoader, arrayOf(ThirdPartyAnnotation::class.java), annotationListener) as ThirdPartyAnnotation
}
}

How to specify "own type" as return type in Kotlin

Is there a way to specify the return type of a function to be the type of the called object?
e.g.
trait Foo {
fun bar(): <??> /* what to put here? */ {
return this
}
}
class FooClassA : Foo {
fun a() {}
}
class FooClassB : Foo {
fun b() {}
}
// this is the desired effect:
val a = FooClassA().bar() // should be of type FooClassA
a.a() // so this would work
val b = FooClassB().bar() // should be of type FooClassB
b.b() // so this would work
In effect, this would be roughly equivalent to instancetype in Objective-C or Self in Swift.
There's no language feature supporting this, but you can always use recursive generics (which is the pattern many libraries use):
// Define a recursive generic parameter Me
trait Foo<Me: Foo<Me>> {
fun bar(): Me {
// Here we have to cast, because the compiler does not know that Me is the same as this class
return this as Me
}
}
// In subclasses, pass itself to the superclass as an argument:
class FooClassA : Foo<FooClassA> {
fun a() {}
}
class FooClassB : Foo<FooClassB> {
fun b() {}
}
You can return something's own type with extension functions.
interface ExampleInterface
// Everything that implements ExampleInterface will have this method.
fun <T : ExampleInterface> T.doSomething(): T {
return this
}
class ClassA : ExampleInterface {
fun classASpecificMethod() {}
}
class ClassB : ExampleInterface {
fun classBSpecificMethod() {}
}
fun example() {
// doSomething() returns ClassA!
ClassA().doSomething().classASpecificMethod()
// doSomething() returns ClassB!
ClassB().doSomething().classBSpecificMethod()
}
You can use an extension method to achieve the "returns same type" effect. Here's a quick example that shows a base type with multiple type parameters and an extension method that takes a function which operates on an instance of said type:
public abstract class BuilderBase<A, B> {}
public fun <B : BuilderBase<*, *>> B.doIt(): B {
// Do something
return this
}
public class MyBuilder : BuilderBase<Int,String>() {}
public fun demo() {
val b : MyBuilder = MyBuilder().doIt()
}
Since extension methods are resolved statically (at least as of M12), you may need to have the extension delegate the actual implementation to its this should you need type-specific behaviors.
Recursive Type Bound
The pattern you have shown in the question is known as recursive type bound in the JVM world. A recursive type is one that includes a function that uses that type itself as a type for its parameter or its return value. In your example, you are using the same type for the return value by saying return this.
Example
Let's understand this with a simple and real example. We'll replace trait from your example with interface because trait is now deprecated in Kotlin. In this example, the interface VitaminSource returns different implementations of the sources of different vitamins.
In the following interface, you can see that its type parameter has itself as an upper bound. This is why it's known as recursive type bound:
VitaminSource.kt
interface VitaminSource<T: VitaminSource<T>> {
fun getSource(): T {
#Suppress("UNCHECKED_CAST")
return this as T
}
}
We suppress the UNCHECKED_CAST warning because the compiler can't possibly know whether we passed the same class name as a type argument.
Then we extend the interface with concrete implementations:
Carrot.kt
class Carrot : VitaminSource<Carrot> {
fun getVitaminA() = println("Vitamin A")
}
Banana.kt
class Banana : VitaminSource<Banana> {
fun getVitaminB() = println("Vitamin B")
}
While extending the classes, you must make sure to pass the same class to the interface otherwise you'll get ClassCastException at runtime:
class Banana : VitaminSource<Banana> // OK
class Banana : VitaminSource<Carrot> // No compiler error but exception at runtime
Test.kt
fun main() {
val carrot = Carrot().getSource()
carrot.getVitaminA()
val banana = Banana().getSource()
banana.getVitaminB()
}
That's it! Hope that helps.
Depending on the exact use case, scope functions can be a good alternative. For the builder pattern apply seems to be most useful because the context object is this and the result of the scope function is this as well.
Consider this example for a builder of List with a specialized builder subclass:
open class ListBuilder<E> {
// Return type does not matter, could also use Unit and not return anything
// But might be good to avoid that to not force users to use scope functions
fun add(element: E): ListBuilder<E> {
...
return this
}
fun buildList(): List<E> {
...
}
}
class EnhancedListBuilder<E>: ListBuilder<E>() {
fun addTwice(element: E): EnhancedListBuilder<E> {
addNTimes(element, 2)
return this
}
fun addNTimes(element: E, times: Int): EnhancedListBuilder<E> {
repeat(times) {
add(element)
}
return this
}
}
// Usage of builder:
val list = EnhancedListBuilder<String>().apply {
add("a") // Note: This would return only ListBuilder
addTwice("b")
addNTimes("c", 3)
}.buildList()
However, this only works if all methods have this as result. If one of the methods actually creates a new instance, then that instance would be discarded.
This is based on this answer to a similar question.
You can do it also via extension functions.
class Foo
fun <T: Foo>T.someFun(): T {
return this
}
Foo().someFun().someFun()