Varargs
Many programming languages have the concept of “varargs”: parameters declared for a method or function that represent zero, one, or several values.
In Java, we use ...
syntax:
void something(String... lots) {
if (lots.size>0) {
// do something
}
}
lots
is treated as a Java array, in this case an array of String
objects.
JavaScript just dumps everything not matched by named parameters into an arguments
array:
function something() {
if (arguments.length>0) {
// do something
}
}
Ruby uses *
syntax:
def something(*lots)
if lots.length > 2
# do something
end
end
Kotlin dedicates the vararg
keyword to this role:
fun main() {
reciprocate(1, 2, 3, 5, 7)
}
fun reciprocate(vararg values: Int) {
values
.map { 1.0 / it }
.forEach { println(it) }
}
Here, reciprocate()
can accept zero parameters, one parameter, or many parameters. We assign the vararg
a name (values
), and the parameters are given to us in the form of an Array
. Here, we use the same code as in the previous section to compute the reciprocal of each of those values and print them to the console.
What You Can Pass In
Typically, a vararg
parameter has values passed in via a comma-delimited list (e.g., reciprocate(1, 2, 3, 5, 7)
). Those do not have to be constants, though:
fun main() {
val foo = 1
val bar = 2
val goo = 3
val baz = 5
val heyWhatComesAfterBaz = 7
reciprocate(foo, bar, goo, baz, heyWhatComesAfterBaz)
}
fun reciprocate(vararg values: Int) {
values
.map { 1.0 / it }
.forEach { println(it) }
}
Any expression, including simple variable references, can be supplied for values.
In addition, Kotlin offers special support for an existing Array
. If you already have an Array
with the values that you want to supply, but the function that you are calling uses vararg
(instead of an Array
parameter), you can use the “spread operator”:
fun main() {
val things = arrayOf("foo", "bar", "goo")
capped(*things).forEach { println(it) }
}
fun capped(vararg strings: String) = strings.map { it.toUpperCase() }
Here, our capped()
function takes a vararg
of String
values and returns them capitalized. We have an Array
of String
values in the form of things
. We can pass things
to capped()
by prefixing things
with *
. This basically says “take the contents of this array and add them each as individual parameters to the function call”.
Since we happened to write capped()
, it would be simpler to just have capped
take an Array
parameter. If capped()
were written by somebody else, though, and they chose to use vararg
, then the spread operator still lets us use our Array
.
Things get a bit strange with types that map to primitives, though. vararg
expects the dedicated array types to be used with the spread operator. So, in the following example, the reciprocate()
function takes a vararg
of Int
. For the spread operator to work, we need to use an IntArray
, not a regular Array
:
fun main() {
val primes = intArrayOf(1, 2, 3, 5, 7)
reciprocate(*primes)
}
fun reciprocate(vararg values: Int) {
values
.map { 1.0 / it }
.forEach { println(it) }
}
Prev Table of Contents Next
This book is licensed under the Creative Commons Attribution-ShareAlike 4.0 International license.