ciscorucinski
11/15/2020, 2:12 PMfun sayHello(greeting: String, vararg names: String) {
names.forEach { name ->
println("$greeting $name")
}
}
fun main() {
val interestingThings3 = arrayOf("Kotlin", "Programming", "Coding")
sayHello(greeting = "Hi", *interestingThings3)
sayHello(greeting = "Hi", names = *interestingThings3)
}
This works, but the last statement suggests to remove Redundant spread (*) operator
. That leads to the following valid code.
fun main() {
val interestingThings3 = arrayOf("Kotlin", "Programming", "Coding")
sayHello(greeting = "Hi", *interestingThings3)
sayHello(greeting = "Hi", names = interestingThings3)
}
Since the last statement doesn't need the spread operator, I thought I would remove it from both
fun main() {
val interestingThings3 = arrayOf("Kotlin", "Programming", "Coding")
sayHello(greeting = "Hi", interestingThings3) // ERROR
sayHello(greeting = "Hi", names = interestingThings3)
}
But this gives an error on the first statement.
Why? Why does the first one error out, but the last one if perfectly fine.nfrankel
11/15/2020, 3:04 PM"Hi"
nfrankel
11/15/2020, 3:05 PMciscorucinski
11/15/2020, 3:25 PMinterestingThings3
is seen as a single parameter. Because of that, it needs to be a String
but it is an Array<String>
. That is why we need the spread operator to split the array into individual `String`s that can be passed in. That makes perfect sense by itself!
However, it seems like when we use named parameters, the Kotlin Compiler treats names
as a "collection" that can be automatically transformed into `String`s that can be passed into the vararg. Again, this makes perfect sense by itself.
The issue is that these 2 methods take to very different approaches that shouldn't be mixed together (my view). To me, it seems like if the Kotlin compiler can figure it out without the spread operator for the named parameters, then it should be able to do that without named parameterskralli
11/15/2020, 3:30 PMArray<String>
is not assignable to String...
like you would expect it from Java. Instead Kotlin requires you to do this conversion explicitly using the spread operator. This gives Kotlin the advantage of mixing arrays with additional arguments, like so sayHello(greeting = "Hi", "Java", "can't", *interestingThings3, "do", "this")
. But this means you cannot pass an array to the function directly.
So why does the second example work? If a vararg
is passed using a named argument instead of a positional argument, then the excepted type is no longer String...
but Array<String>
. Kotlin does automatically convert String...
to Array<String>
, so the spread operator used in the second call becomes redundant. Basically its converting Array<String>
to String...
and then immediately back to Array<String>
.kralli
11/15/2020, 3:37 PMString...
has to become Array<String>
in order to be passable as a single argument. So it’s not possible to write something like this sayHello(greeting = "Hi", names = "Java", "can't", *interestingThings3, "do", "this")
. Instead you have to write something like this ``sayHello(greeting = "Hi", names = arrayOf("Java", "can't", *interestingThings3, "do", "this"))`.ciscorucinski
11/15/2020, 4:04 PMkenkyee
08/18/2021, 12:57 AMkenkyee
08/18/2021, 12:57 AM