Using spread oeprator for vararg args in operator get

I am trying to implement a function operator fun get(vararg objects: Any). I can call this function successfully via get(1, 2, 3), get(arrayOf(1, 2, 3), and [1, 2, 3]. [*arrayOf(1, 2, 3)], however, results in a compilation error. Have a look at this MWE:

class VarargOperatorGet {
    companion object {
        operator fun get(vararg objects: Any) = objects.joinToString(" ", prefix = "{", postfix = "}")
    }
}

fun main() {
    // all these work as expected
    println(VarargOperatorGet.get(1, 2, 3))
    println(VarargOperatorGet[1, 2, 3])
    println(VarargOperatorGet.get(*arrayOf(1, 2, 3)))
    // does not compile:
    // VarargOperatorGet[*arrayOf(1, 2, 3)]
}

Uncommenting the last line results in this compilation error:

Error:(13, 23) Kotlin: Expecting an expression
Error:(13, 23) Kotlin: Unresolved reference. None of the following candidates is applicable because of receiver type mismatch: 
@InlineOnly public inline operator fun BigDecimal.times(other: BigDecimal): BigDecimal defined in kotlin
@InlineOnly public inline operator fun BigInteger.times(other: BigInteger): BigInteger defined in kotlin
Error:(13, 40) Kotlin: Unexpected tokens (use ';' to separate expressions on the same line)

According to IntelliJ, kotlin language version is 1.3, API version is 1.3.

Of course, I can always fall back to .get() for the array with spread operator case, but being able to consistently use [] would be great. Is this

  • a conscious language design choice, or
  • a bug that might be resolved in a later version of kotlin?
1 Like

Just ran into this myself. It is a corner case that many are not going to run into but I found it annoying as well.

1 Like

There is an issue for this https://youtrack.jetbrains.com/issue/KT-20113

1 Like

I notice also that [ ] does not have feature parity with invoke for default parameters as well:

class Foo {
    operator fun get(a: Int = 0, b: String = ""): Int = TODO()
    fun foo(a: Int = 0, b: String = ""): Int = TODO()
}

fun test(f: Foo) {
    // These work
    f.foo()
    f.foo(a = 5)
    f.foo(b = "foo")
    f.foo(b = "foo", a = 5)
    f[5]

    // These do not
    f[]
    f[a = 5]
    f[b = "foo"]
    f[a = 5, b = foo]
}

Guess I need to rethink some of the tricky things I was trying to do with [ ]

2 Likes