Reputation: 4022
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
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
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 with
s 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
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
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