I know the meaning of "this expression" in almost language. But below code in Kotlin make total confuse:
fun <A, B, C> (A.(B) -> C).swap(): (B.(A) -> C) = { a: A -> // 1
a.this@swap(this)
}
the interpret phrase for the function definition is that: "swap
as a function that converts a function of type A.(B)->C
in a function
of type B.(A)->C
, basically swapping the receivers of types A
and B
.
a.this
is something i can not get. If just this
in that place, i will understand the scope are belong to (A.(B) -> C).
a.this@swap
is a monster now, and a.this@swap(this)
is the brain explode.
is that true if i think a.this
is "outside" of a
, but if that is, i also do not get what it is. Sorry for my English.
The code as written is indeed very confusing and unreadable. To understand it, let's start with a function that turns a (A, B) -> C
to a (B, A) -> C
:
fun <A, B, C> swap(f: (A, B) -> C): (B, A) -> C = { b, a ->
f(a, b)
}
Hopefully this is straightforward enough to not need any explanation.
Instead of (A, B) -> C
and (B, A) -> C
, let's change this function to work with A.(B) -> C
and B.(A) -> C
. These function types have a receiver. B.(A) -> C
still takes two parameters B
and A
, but B
is the receiver. This means that it is referred to as this
inside a function of that type.
So in the lambda, we remove the first parameter b
(that's the receiver now), and refer to it using this
.
fun <A, B, C> swap(f: A.(B) -> C): B.(A) -> C = { a ->
// here, "this" refers to the receiver of the returned function, of type B
f(a, this)
}
Note that since f
has A
as the receiver, f(a, this)
can be alternatively written as a.f(this)
. Let's do that instead:
fun <A, B, C> swap(f: A.(B) -> C): B.(A) -> C = { a ->
// same as f(a, this)
a.f(this)
}
The functions we have written so far all take a parameter f
. What if we made this parameter the receiver of swap
? In other words, we write swap
as an extension function of A.(B) -> C
.
Think about how you would refer to the receiver of swap
inside the lambda you return. this
inside the lambda would refer to the receiver of the returned B.(A) -> C
, since that's the "closest" receiver. You would need to use a qualified this
- this@swap
.
So we can replace f
with this@swap
, and we reach the code in the question:
fun <A, B, C> (A.(B) -> C).swap(): B.(A) -> C = { a ->
// this@swap refers to the receiver of swap
// this refers to the receiver of the returned lambda i.e. an instance of B
a.this@swap(this)
}
IMO, this@swap(a, this)
is more readable.