Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does Kotlin need function reference syntax?

Tags:

kotlin

Kotlin docs stated that it supports higher-order functions. Why would the language even need a ::function syntax when passing a top level function as an argument?

Given:

fun isOdd(x: Int) = x % 2 != 0
val numbers = listOf(1, 2, 3)
println(numbers.filter(::isOdd)) // here.

Why not just

fun isOdd(x: Int) = x % 2 != 0
val numbers = listOf(1, 2, 3)
println(numbers.filter(isOdd)) // simple and makes more sense

More on the function reference syntax here.

like image 661
Yudhistira Arya Avatar asked Apr 13 '17 15:04

Yudhistira Arya


People also ask

What is function reference in Kotlin?

Kotlin supports the notion of first-class functions - functions can be saved to variables, passed into functions, and returned from functions. When you need to do this, you can create lambdas - function literals - or you can refer to an existing function by means of a function reference.

What is the use of function in Kotlin?

A function is a unit of code that performs a special task. In programming, function is used to break the code into smaller modules which makes the program more manageable. For example: If we have to compute sum of two numbers then define a fun sum().

Is Kotlin pass by value or reference?

I.e., the arguments to the function are passed by value and not by reference. Trying this in Kotlin, the compiler will help you out by saying that you can't reassign a val. So Kotlin declares the arguments to functions as values, equivalent to java finals.

Why would you want to use the function type notation instead of just the lambda?

Fact is that this notations can be used interchangeably, but it is better to use anonymous functions when we need to use return more then once. Lambda expression should be preferred for small functions with single expression. Although there are some cases when it is better to use anonymous function instead.


2 Answers

Kotlin language design tries to avoid ambiguous situations where some absence of something could be both correct and incorrect syntax at the same time. For example if you allowed the proposed syntax:

isOdd     // error, function invocation expected isOdd(...)
isOdd     // not error, you have a function reference

The :: is a clear signal as to the intent. Because of this, you get only an error in the isOdd case because you now have possibilities that do not overlap:

isOdd      // error, function invocation expected isOdd(...)
::isOdd    // function reference
isOdd()    // error, missing parameter x
isOdd(x)   // function call

This is why Kotlin avoids things that lead to ambiguous states. Your eyes can also quickly pick up the problem, just as the IDE and static analysis can, just as the compiler does. If you start allowing this looser syntax you will start running into compounded ambiguities such as when using as infix functions and so on. Language design is more complicated than "oh, let's make them type less characters" because the complexity matrix is much larger than you imagine if you only look at one use case ignoring all the others.

like image 72
5 revs Avatar answered Sep 30 '22 17:09

5 revs


Because Java (and, therefore, Kotlin) uses separate namespaces for fields and methods, you need :: to avoid ambiguities. Example:

val isOdd : (Int) -> Boolean = { x -> x % 2 != 0 }
fun isOdd(x: Int): Boolean {
    return x % 2 != 0
}

val odds = listOf(1,2,3).filter(isOdd) // uses the val version
val otherOdds = listOf(1,2,3).filter(::isOdd) // uses the fun version
like image 22
pdpi Avatar answered Sep 30 '22 19:09

pdpi