cuihtlauac
cuihtlauac

Reputation: 1878

Type name as value?

Can somebody point me to the documentation explaining what the following means? Especially, I'd like to know why String and Int can be used as shown.

val a: Unit = { _: Any -> String }(Int)

Initially, I had written this:

val a: Unit = { x: Any -> x.toString() }(Unit)

In both cases, I've failed to find the right documentation.

Upvotes: 0

Views: 507

Answers (3)

Salem
Salem

Reputation: 14907

Type name as value?

String and Int are the companion objects (sort of the equivalent to Java's static) of the String and Int classes. The name of a class is synonymous with the name of its companion object, i.e. Int more or less is the same as Int.Companion, etc.

{ _:Any -> String } and { x:Any -> x.toString() } are both lambdas of type (Any) -> String.Companion and (Any) -> String, but since the result of the function call is assigned to a, which is of type Unit, these functions are both inferred to return Unit.

Basically, after type inference:

{ _:Any -> String } is a (Any) -> Unit

{ x:Any -> x.toString() } is also a (Any) -> Unit

This type corresponds to the void type in Java.

Documentation: Unit

So these functions both effectively do nothing.

The first function (of type (Any) -> Unit takes one argument (which is unused) and returns String.Companion.

In this case, it is called with Int.Companion... but the argument is unused, so it doesn't matter.

You could have written:

val lambda: (Any) -> Unit = { _: Any -> String }
val a: Unit = lambda(Int)

The second function calls toString on its parameter, which is in this case Unit. The string representation of Unit is defined as "kotlin.Unit", but since it is assigned to a the function's return type is inferred to be Unit, so the function doesn't return anything useful.

These functions are both quite useless as they return Unit (i.e. void, nothing). What do you want to accomplish?

Upvotes: 4

s1m0nw1
s1m0nw1

Reputation: 81889

You defined a lambda { _: Any -> String } of type (Any)-> String.Companion and called it with the Int.Companion object. It always returns the String.Companion object. Does not make much sense. The following might be more readable:

val func = { _: Any -> String.Companion }
val res = func(Int.Companion)

Note that Int and Int.Companion are used interchangeably here (also applies for the String one).

Information about companion objects can be found in the documentation.

Upvotes: 3

zsmb13
zsmb13

Reputation: 89548

Let's break down the first line.

{ _: Any -> String }

This is a lambda. It takes one parameter, that's marked as never used by giving it the name _. The parameter of this type is specified as Any. The lambda returns String, which refers to the (completely empty) companion object inside the String class. The type of this lambda is therefore (Any) -> String.Companion.

{ _: Any -> String }(Int)

This lambda is invoked by the parentheses after it, passing in Int, which again refers to the companion object inside that class (this one isn't empty, it contains constants). This works, because of course, Int.Companion is a subtype of Any, the expected parameter type.

val a: Unit = { _: Any -> String }(Int)

Finally, the declaration of a with its explicit Unit type forces the lambda to change its inferred type from (Any) -> String.Companion to (Any) -> Unit, so it can return the expected explicit type after it's invoked.

The second line is more of the same, only simpler without the companion objects.

Upvotes: 6

Related Questions