Reputation: 1878
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
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.
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
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
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