Unary operator before lambda with receiver

Hello!

Can’t get working + { i = 5 } where I overload + for lambda with a receiver C.() -> Unit. I see the error:

Unresolved reference. None of the following candidates is applicable because of receiver type mismatch: public operator fun (C.() -> Unit).unaryPlus(): Unit

The full example:

class C {
    var i: Int = 0
}

operator fun (C.() -> Unit).unaryPlus() {
    val x = C().apply(this)
    println("unary plus; i=${x.i}")
}

fun main() {
    + { i = 5 }
}

I can work this around either by specifying the type of the lambda explicitly:

…

…

fun main() {
    val f: C.() -> Unit = { i = 5 }
    + f
}

or by replacing the unary operator with a named function:

…

fun p(f: C.() -> Unit) {
    val x = C().apply(f)
}

fun main() {
    p { i = 5 }
}

But is it possible to get working the original idea + { i = 5 } ?


Thank you!

+ { i = 5 }

is the same as:

{ i = 5 }.unaryPlus()

Regular and dotted function calls are resolved differently:

  • In a normal call, compiler must first compose a list of possible call targets in the current scope, and then match the concrete implementation by the types of arguments.
  • When called through a dot, compiler must first understand the type of the receiver, and then, based on it, make a list of possible targets. In your case, the compiler cannot determine the receiver type.

Also, there is no way to specify receiver type in lambda literal. So, answering your question:

no, it’s not possible.