счёт резолвинга ресиверов?
2. как должны работать экстеншены юзающие два раза один и тот же контекст?
data class A(val value: Int)
typealias AA = A
fun [A, AA].printSum() = println(value + this@A.value)
with(A(1)) {
with(A(2)) {
printSum()
}
}
Я так понимаю в твоём варианте резолвинга это выведет 4, верно? (В таком случае это не имеет никакого смысла, т.к. может быть просто экстэншеном к [A])
2.2 как работает this в случае одинаковых ресиверов?
fun [A, A].printSum() = println(value + this@A.value)
Мой ответ на 2.2: есть два варианта:
(1) Запретит такое вообще (compilation error)
(2) сделать возможность именовать ресиверы. Типа:
fun [first: A, second: A].printSum() = println(first.value + second.value)
// ИЛИ
fun [A as first, A as second].printSum()
= println(first.value + second.value)
// ИЛИ
fun [first@ A, second@ A].printSum()
= println(this@first.value + this@second.value)
К такому варианту ещё вопросы
(1) ссылается ли this на second (или для такого поведения надо убрать именование второго параметра)?
(2) существуют ли в таком случае указатели this@first, this@second ? (в варианте first@... очевидно — да)
(3) куда указывает this@A (если он указывает хоть куда-то)
3. Нужно ли явно указывать this@ если у ресиверов не пересикаются поля?
data class A(val a: String = "A")
data class B(val b: String = "B")
data class C(val c: String = "C")
fun [A, B, C].printSum() = c + b + a
// ИЛИ
fun [A, B, C].printSum() = c + this@B.b + this@A.a
4. Как происходит вызов без контекста? (используется код из вопроса 3)
val a = A()
val b = B()
val c = C()
[a, b, c].printSum() // Мой фаворит
a.b.c.printSum() // b и c выглядят как поля
(a, b, c).printSum() // похоже на синтаксис присваивания data классов / Pair / etc
4.1 вызов с частичным контекстом? (используется код из вопроса 3)*
with(A()) {
with(C()) {
[_, B(), _].printSum()
(_, B(), _).printSum()
_.B()._.printSum()
// Ничего лучше не придумал
}
}
* это скорее предложение, а не вопрос
5. Это не совсем в тему, но при наличии множественных контекстов наверное должна присутствовать функция:
fun <T1, T2> with(receiver1: T1, receiver2: T2, block: [T1, T2].() -> Unit) = [receiver1, receiver2].block()
(и подобные с 3-4 ресиверами видимо...)
override fun print() = print(this)
}
Прям в экран не влезает. 1. Не пришли, вот я последний пост сегодня написал, он вроде все учитывает. Дальше буду делать KEEP PR. 2. Ну эта конкретно штука будет запрещена, по скольку это оди и тот же класс. Но если подтипы, то они отрезолвятся к ондому и тому же объекту. Как правильно отметил Илья Горбунов, оно сейчас так и работает. 2.2 запрещены одинаковые ресиверы как раз по этой причине. Кстати, там этого нет, но подтипы тоже надо запретить. Именованые ресиверы - это слишком сложно. 3. Тут все как в мембер экстеншенах. Если есть однозначность, то ничего не надо (можно ворнинг кидать, если что-то перекрывается). Если нет однозначности, то ошибка. 4. with(a){with(b){with(c){...}}} можно упростить до with(a,b,c){} 4.1 Не, это по-моему уже ересь. 5. да, конечно 6. Там как раз отличие от тайп классов в том, что для вызова экстеншен интерфейса надо явно экземпляр контекста подсунуть. Байндинга по типам нет.
Обсуждают сегодня