Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does one pass an Array<Int> to a vararg Int function using the Spread Operator?

I have a vararg function that takes multiple Ints. I have an Array<Int> that I'd like to use as input.

An unsuccessful attempt:

Here is my attempt to call the function using the Spread Operator:

fun printNumbers(vararg numbers: Int) {
    numbers.forEach { it -> println(it) }
}

val numbers: Array<Int> = arrayOf(1, 2, 3)
printNumbers(*numbers)

However, I'm getting the following type mismatch error:

error: type mismatch: inferred type is Array<Int> but IntArray was expected
printNumbers(*arrayOf<Int>(1, 2, 3))
              ^

Extra confusion:

I don't understand why I'm getting this error, especially since I can use the spread operator on an Array<String>. For example...

fun printStrings(vararg strings: String) {
    strings.forEach { it -> println(it) }
}

val strings: Array<String> = arrayOf("hello", "there", "stackoverflow")
printStrings(*strings)

Output:

hello
there
stackoverflow

Attempts to correct the error:

  • I searched online to see if it was possible to convert an Array<Int> to an IntArray, as this might satisfy the compiler. I couldn't see anything except the opposite conversion (IntArray to Array<Int>)

  • I tried specifying the generic type when calling arrayOf. E.g. arrayOf<Int>(1, 2, 3). This (for obvious reasons) didn't work.

Notes:

  • I'm using Kotlin version 1.0.3

  • I think some of my confusion stems from the fact that I don't understand the difference between Array<Int> and IntArray and when to choose one over the other.


How do I pass an Array<Int> into a vararg function that expects multiple Ints?

like image 830
byxor Avatar asked Feb 18 '18 19:02

byxor


Video Answer


2 Answers

Basically, Array<Int> is an array of boxed Integer objects under the hood, while IntArray translates to an array of primitive int values (see this answer).

To pass in an Array<Int> to a vararg function, you can use the toIntArray() function to convert it to an IntArray first:

val numbers: Array<Int> = arrayOf(1, 2, 3)
printNumbers(*numbers.toIntArray())

Or if you can, create the array as an IntArray to begin with - this way you avoid the allocation of an extra array in the process, as well as the boxing of each individual value:

val numbers: IntArray = intArrayOf(1, 2, 3)
printNumbers(*numbers)
like image 156
zsmb13 Avatar answered Sep 30 '22 18:09

zsmb13


The problem is that you're using the boxed Integers when creating an Array<Int>. This does not work well with vararg Int. It works with an IntArray though:

val numbers: Array<Int> = arrayOf(1, 2, 3)
printNumbers(*numbers.toIntArray())

Or directly create the array with the correct type:

val numbers = intArrayOf(1, 2, 3)
printNumbers(*numbers)

Using an IntArray, as opposed to Array<Int>, removes the boxing overhead, which surely is preferable.

like image 42
s1m0nw1 Avatar answered Sep 30 '22 17:09

s1m0nw1