Found an interesting (to me that is) trivia: ``` f...
# announcements
t
Found an interesting (to me that is) trivia:
Copy code
fun main(vararg args: String) {
	fun toCall(arg: String) = println("fun: $arg")
	val toCall = fun (arg: String) = println("val: $arg")
	toCall("hello")
}
What happens? (spoilers in thread) 1: outputs "fun: hello" 2: outputs "val: hello" 3. fails to compile
also as a followup: How do you make it output the other thing? Can you explain why it picks the one it picks?
k
Normally calls the function but when you do
toCall.invoke("hello")
it uses the val.
No idea why though.
l
So it picks the function probably because it's closer to a proper JVM function. Behavior is the same on Kotlin/JS BTW. As @karelpeeters said,
invoke(…)
is the way to call the
val
version. It reminds me how an extension can be shadowed by a member. This is a similar story here, where the hard defined function wins over the syntactic sugar for the
invoke
operator on a functional type.
t
if found that
(toCall)("hello")
also uses the
val
, I guess that's the forced version of
.invoke()
k
@louiscad This is definitely a compile time thing, functions in other functions aren't just compiled to normal vals.
t
top level, or class body yields the same, it's just a minimal example
k
I don't understand why this compiles, this should really be an error.
BTW you could add it to the puzzlers: https://github.com/angryziber/kotlin-puzzlers
t
@karelpeeters why do you expect failure? "overload resolution", or "declaration conflict"?
k
Just a conflict? No one expects
Copy code
val v = 5
val v = "hey"
println(v.subString(2))
to work either.
t
true, but considering
val
is
getToCall
while
fun
is just
toCall
there's no conflict in
.class
I guess interop
k
Sure but those are all implementation details, eg. in JS it's a different story. Those things aren't relevant though, I'm talking about language design.
t
we can throw in another level of `?!`:
Copy code
fun f(toCall: (String) -> String) {
	fun toCall(arg: String): String =
		"fun: $arg"
	val toCall = fun(arg: String) =
		"val: $arg"
	println(toCall("called"))
}
k
That's val just shadows the parameter one, right?
t
oh, yeah, warning is shown