Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Kotlin: why can't I store a function in a variable?

Why do i have to use function reference to store a function into a variable:

fun someFunction(i: Int): Unit = println(i)
val funVal = someFunction  // Compile error!
val funVal2 = ::someFunction // Function reference works fine

But I can store lambda in a variable directly:

val someLambda: (Int) -> Unit = { i: Int -> println(i) }
like image 374
y.allam Avatar asked Dec 15 '18 19:12

y.allam


People also ask

Can you store a function in a variable?

Functions stored in variables do not need function names. They are always invoked (called) using the variable name. The function above ends with a semicolon because it is a part of an executable statement.

Can functions in Kotlin be assigned to variables?

Functions as variables. Functions in Kotlin are simply another data type. You can assign them to variables and constants just as you can any other type of value, such as an Int or a String . This function takes two parameters and returns the sum of their values.

Can I pass a function as a parameter in Kotlin?

Kotlin gives us the power to declare high-order functions. In a high-order function, we can pass and return functions as parameters.

How do you declare a variable to a function in Kotlin?

Kotlin uses two different keywords to declare variables: val and var . Use val for a variable whose value never changes. You can't reassign a value to a variable that was declared using val . Use var for a variable whose value can change.


3 Answers

It is about correct syntax. Or more precisely, about the ability of the compiler to understand what you are trying to tell it!

When you look at your different examples, you can find that the accepted cases use specific chars, like the colon for example. That makes it simply easier to deduct what the code is meant to say.

So, one possible reason could be a trade off. Sure, when you have

val a = b

you could allow b to be a method reference. But what if you wanted to call b() instead?! The "lexicographic" distance between b and b() is pretty small!

So to not allow for that syntax makes it a) easier to parse code, and b) harder for you to have small typos change the meaning of your code!

like image 68
GhostCat Avatar answered Oct 13 '22 00:10

GhostCat


Because fun someFunction(i: Int): Unit = println(i) despite being a function is a more concrete type called method, that's why you need the method reference syntax. Something similar happens in Scala too

Example

fun method(value: String) = println(value)
val function: (String) -> Unit = { value -> println(value) }

val methodRef = ::method
val functionRef = function

Further reading "Kotlin programmer dictionary"

  • Function vs Method vs Procedure
  • Function Type vs Function literal vs Lambda expression vs Anonymous function
like image 4
Omar Mainegra Avatar answered Oct 13 '22 00:10

Omar Mainegra


The GhostCat's answer is quite correct, but it's missing an important point, which I think should be mentioned to make it complete.

The callable references syntax is uniform across functions and properties, but in case of properties, it is absolutely necessary to distinguish the property access foo from its callable reference ::foo.

val foo: Int = TODO()
val fooValue = foo
val fooReference = ::foo

So, while functions in fact could get callable reference syntax with just the function name foo (it is not ambiguous with the function call foo() in any way), for uniformity, functions share the callable reference syntax ::foo with properties, which in turn needed some special syntactic form of callable references.

like image 4
hotkey Avatar answered Oct 13 '22 00:10

hotkey