svkaka
svkaka

Reputation: 4022

Kotlin `with` with multiple params

I really like how with behaves. Is it possible to extend with so it works with multiple params.

I want to use with like this.

with(foo, bar){
    fooFunction()
    barFunction()
}

Upvotes: 1

Views: 286

Answers (4)

user2956272
user2956272

Reputation:

First, I strongly against it.

One can come close to what you want:

data class A(val a: Int)
data class B(val b: Int)

fun<S, T> withPair(a: S, b: T, f: S.() -> T.() -> Unit) {
    val g = a.f()
    b.g()
}

fun main() {
    withPair(A(1), B(2)) {{
        print(a)
        print(b)
    }}
}

So you can have a block function which return a block function. You need nested lambdas though.

Upvotes: 1

Bartek Lipinski
Bartek Lipinski

Reputation: 31438

It's impossible to do this with the standard with function because it cannot have two receiver types of the lambda (accessed by this).

with(foo, bar){
    fooFunction() //`this` would have to mean `foo`
    barFunction() //`this` would have to mean `bar`
}

Nesting two withs is nasty. It can cause all sort of issues, with this ambiguity...


That said, you can create your own with function that will work similarly to the standard one, but will not use passed extension fun (so no receiver type "hidden" behind this), but a regular lambda with two arguments:

inline fun <T1, T2, R> with(t1: T1, t2: T2, block: (T1, T2) -> R): R {
    return block.invoke(t1, t2)
}

//then:
with(foo, bar) { f, b ->
    f.fooFunction()
    b.barFunction()
}

Upvotes: 0

David Soroko
David Soroko

Reputation: 9086

Another possibility is to use a Pair, something like:

with( Pair("abc" , listOf(1,2,3)) ) {
    println(first.plus("d"))
    println(second.reversed())
}

Prints:

abcd [3, 2, 1]

Upvotes: 0

Alexey Romanov
Alexey Romanov

Reputation: 170735

I don't think it's possible to write a function which behaves like this, but with the standard with you can write

with(foo) {
    with(bar) {
        fooFunction()
        barFunction()
    }
}

(note that if a method is available on both foo and bar, this way the bar method will be called).

Upvotes: 0

Related Questions