Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using multiple generic types in lambda in kotlin

Koltin 1.2.30

I am working with generic and lambda functions.

The following works without the generic types

fun onScanExt(): (Int, Int) -> Int = {
    num1, num2 -> num1 + num2

    num1 + num2
}

However, with the generics:

fun <T, R> onScanExt(): (T, T) -> R = {
    num1, num2 -> num1 + num2

    num1 + num2
}

I guess the above cannot work as the generic type might not be a Number type and someone could pass in a String and the lambda wouldn't know what to do with a String type if there is a calculation involved.

Any suggestions of example on how to pass in multiple generics and return a generic type?

Many thanks in advance,

like image 283
ant2009 Avatar asked May 23 '18 01:05

ant2009


2 Answers

You're right: The generics, as you used them, allow any type to be used, even the ones that don't offer the + operator for example. Specifying the type to be Number is easy. However, it won't make the function compile either:

fun <T : Number> onScanExt(): (T, T) -> T = { 
    num1, num2 -> num1 + num2
}

(Note that a second type parameter R is not necessary in your example.)

The problem again is that even Number does not include the + operator in its contract. These are defined for the specific types Int, Double et cetera directly (see source).

A strongly typed language such as Kotlin won’t allow such an implementation.

like image 83
s1m0nw1 Avatar answered Nov 12 '22 19:11

s1m0nw1


There's no reasonable way to write anything with signature

fun <T, R> onScanExt(): (T, T) -> R

because it says that the caller can choose any T and R, and then you need to obtain an R from two Ts; but there's no relationship between T and R, so you can't use the Ts.

You can make it compile: e.g. use someExpression as R, or throw SomeException(), or an infinite loop. But none of these are actually useful.

In general (C++ is the big exception here; its templates work very differently), a generic method must either:

  1. Work on all types (or, in Java, on all types except primitives). So it can only use operations available on all types, and there are very few of those. An example with two type parameters would be

    fun <T1, T2> apply(f: T1 -> T2, x: T1) = f(x)
    
  2. Work on all types which satisfy some constraints. Different languages allow different kinds of constraints; e.g. C# has a pretty large set, Scala has view and context bounds. Kotlin, so far as I am aware, only allows upper bounds. In particular, there's no constraint which says "type T has operator +". So the function you want can't be written.

like image 28
Alexey Romanov Avatar answered Nov 12 '22 19:11

Alexey Romanov