jpganz18
jpganz18

Reputation: 5858

is there any way I send a nullable Function<T,R> as parameter in Kotlin?

I am trying to use the public interface Function (as I learned it in Java) in Kotlin.

For this I created my method

fun foo(input: List<String>, modifier1: Function<List<String>>? = null){

}

as far I remember here I should be able to do modifier1.apply(input)

but seems like it is not possible (it is possible to do modifier1.apply{input} though)

Reading more about it I found this:

Kotlin: how to pass a function as parameter to another?

So I changed my method signature to this:

fun foo(input:String,  modifier2: (List<String>) -> (List<String>){
}

Here I am able to do modifier2(input)

and I can call foo this way

service.foo(input, ::myModifierFunction)

where

fun myModifierFunction(input:List<String>):List<String>{
   //do something
   return input
}

So far this seems possible but it is not acceptable to have the function reference as nullable, is there any way I can do that? or use Function ?

Upvotes: 1

Views: 556

Answers (3)

gidds
gidds

Reputation: 18557

You can make the reference nullable simply with ? — the only wrinkle is that the whole function type needs to be in parens first:

fun foo(input: String,  modifier2: ((List<String>) -> List<String>)? = null) {
}

As required, modifier2 is optional; if specified, it may contain null, or it may contain a function taking and returning a list of strings.

As mentioned in another answer, kotlin.Function is not the same as java.util.function.Function — though in practice you shouldn't need to refer to either directly, as the -> notation is simpler.

Upvotes: 1

Roland
Roland

Reputation: 23242

You were using kotlin.Function instead of java.util.function.Function in your first example. Note that the latter takes 2 generic types: 1 for the incoming parameter and 1 for the resulting one.

The apply method you saw is the default Kotlin one: apply, not the one of Java's Function-interface.

If you really want to have the Java-function as nullable type the following should work:

fun foo(input: List<String>, modifier1: java.util.function.Function<List<String>, List<String>>? = null) {
    modifier1?.apply(input) ?: TODO("what should be done if there wasn't passed any function?")
}

Kotlin variant for the same:

fun foo(input: List<String>, modifier1: ((List<String>) -> List<String>)? = null) {
     modifier1?.invoke(input) ?: TODO("what should be done if there wasn't passed any function?")
}

Maybe also a default function, such as { it } instead of null might better suite your needs? (Java variant would be Function.identity()):

// java   modifier1 : Function<List<String>, List<String>> = Function.identity()
// kotlin modifier1 : (List<String>) -> List<String> = { it }

Upvotes: 2

zsmb13
zsmb13

Reputation: 89548

If you want to pass in a function that takes List<String> as its parameter and returns nothing meaningful, the type for you is Function1<List<String>, Unit>. The method name for invoking a function is invoke(), which you could also do with just regular parentheses, if it wasn't nullable. All in all, your code could look something like this:

fun foo(input: List<String>, modifier1: Function1<List<String>, Unit>? = null) {
    modifier1?.invoke(input)
}

The 1 in the typename of Function1 means that it's a one parameter function, there's also Function0, Function2, etc.

The Function type on its own is not something you can use to call that function, as it's an empty marker interface. All functions implement this regardless of how many parameters they have.

Upvotes: 0

Related Questions