Size: a a a

Kotlin Community

2020 February 24

IK

Igor Komarov in Kotlin Community
Такой вопрос. Допустим, я делаю тайпкласс, который будет мне везде проставлять некоторый контекст "J":

interface Context<J> {
 
}


Все прекрасно, контекст всегда можно подставить, до того злосчастного момента, когда мне нужно, чтобы контекст предоставлял "J" в функцию с reified тайп-параметром:

inline fun <J, reified A: Any> Context<J>.f(key: String) = TypedFieldLens<J>(key, A::class)


Сделать inline внутри контекста я не могу. Сделать только параметр A вне контекста я тоже не могу. Я в некотором тупике..
источник

AT

Alexey Tkachenko in Kotlin Community
Igor Komarov
Такой вопрос. Допустим, я делаю тайпкласс, который будет мне везде проставлять некоторый контекст "J":

interface Context<J> {
 
}


Все прекрасно, контекст всегда можно подставить, до того злосчастного момента, когда мне нужно, чтобы контекст предоставлял "J" в функцию с reified тайп-параметром:

inline fun <J, reified A: Any> Context<J>.f(key: String) = TypedFieldLens<J>(key, A::class)


Сделать inline внутри контекста я не могу. Сделать только параметр A вне контекста я тоже не могу. Я в некотором тупике..
Скорее всего, так сделать не получится из-за отсутствия нестираемых дженериков
источник

IK

Igor Komarov in Kotlin Community
Ну, аналогичный пример у меня работает, сейчас покажу код для контекста. Проблема именно с inline/reified. Котлин сейчас адекватного способа подставить из двух мест дженерики не предоставляет при создании extension функции к сожалению (и вот тут возможно я не прав)
источник

IK

Igor Komarov in Kotlin Community
Вот по-сути у меня есть функция. Один тайп-параметр подставляется из контекста, один – из функции. Неужели того же нельзя сделать для inline в extension O.o?
источник

QH

Quantum Harmonizer in Kotlin Community
TIL: @Suppress("INAPPLICABLE_JVM_NAME")
источник

AT

Alexey Tkachenko in Kotlin Community
а почему бы не написать так?
inline fun <reified J, reified A: Any> Context<J>.f(key: String) = TypedFieldLens<J>(key, A::class)
источник

IK

Igor Komarov in Kotlin Community
Alexey Tkachenko
а почему бы не написать так?
inline fun <reified J, reified A: Any> Context<J>.f(key: String) = TypedFieldLens<J>(key, A::class)
Так написать можно, но в дальнейшем у меня ведь не будет проходить вызов как:

with (context) {
   f<Double>("key")
}


То есть, мне всегда нужно будет вызывать ее как:

with (context) {
   f<J, Double>("key")
}


Единственный способ обойти это как я вижу – это использовать auto type cast котлина, то есть – каждый вызов функции присваивать отдельной переменной типа

with (context) {
   val d: TypedFieldLens<J, Double> = f("key")
}`
источник

IK

Igor Komarov in Kotlin Community
Но это конечно не решение проблемы.
источник

QH

Quantum Harmonizer in Kotlin Community
Дык откуда должен взяться type argument для параметра A?
источник

IK

Igor Komarov in Kotlin Community
Вот его я как-раз и хочу чтобы можно было указать, но мне при этом абсолютно не хочется указывать параметр J, что я хотел решить через контекст
источник

QH

Quantum Harmonizer in Kotlin Community
Igor Komarov
Вот его я как-раз и хочу чтобы можно было указать, но мне при этом абсолютно не хочется указывать параметр J, что я хотел решить через контекст
а, можно сделать функцию-пустышку, которая прокинет этот тип
fun <T> t(): Empty<T> = EmptyImpl as Empty<T>
interface Empty<T>
object EmptyImpl : Empty<Nothing>

соответственно, f("key", t<Double>())
источник

IK

Igor Komarov in Kotlin Community
Прикольно. Но боюсь, что многословно. В любом случае спасибо, подумаю в сторону изменений API чтобы можно было как-то переключаться между типами/общими описаниями
источник

D

Danil Yudov in Kotlin Community
возвращаясь к мультиплатформенным либам. у меня есть зависимость на ktor-client, можно ли как-то настроить грэдл, чтоб он сам резолвил зависимость для конкретного sourceSet? а не писать для каждого по отдельности (а ля io.ktor:ktor-client-core-js, io.ktor:ktor-client-core-linuxx64)
источник

AO

Alexey Otts in Kotlin Community
Igor Komarov
Так написать можно, но в дальнейшем у меня ведь не будет проходить вызов как:

with (context) {
   f<Double>("key")
}


То есть, мне всегда нужно будет вызывать ее как:

with (context) {
   f<J, Double>("key")
}


Единственный способ обойти это как я вижу – это использовать auto type cast котлина, то есть – каждый вызов функции присваивать отдельной переменной типа

with (context) {
   val d: TypedFieldLens<J, Double> = f("key")
}`
Я бы предложил тебе сделать обёртку для контекста, в котором были бы эти inline функции. И вызывать with на этой обёртке, тогда ты зафиксируешь свой J
источник

AN

Alexander Nozik in Kotlin Community
Alexey Otts
Потому что это логика в конструкторе и неявности в сабтайпинге
Вообще мысль-то правильная
источник

IK

Igor Komarov in Kotlin Community
Alexey Otts
Я бы предложил тебе сделать обёртку для контекста, в котором были бы эти inline функции. И вызывать with на этой обёртке, тогда ты зафиксируешь свой J
Но тогда получится что придется это писать для каждой обертки. В целом идея, но пока-что наверное остановлюсь на варианте с коротенькой функцией для создания kclass
источник

AN

Alexander Nozik in Kotlin Community
Igor Komarov
Такой вопрос. Допустим, я делаю тайпкласс, который будет мне везде проставлять некоторый контекст "J":

interface Context<J> {
 
}


Все прекрасно, контекст всегда можно подставить, до того злосчастного момента, когда мне нужно, чтобы контекст предоставлял "J" в функцию с reified тайп-параметром:

inline fun <J, reified A: Any> Context<J>.f(key: String) = TypedFieldLens<J>(key, A::class)


Сделать inline внутри контекста я не могу. Сделать только параметр A вне контекста я тоже не могу. Я в некотором тупике..
Я пока не вижу, в чем проблема. Если надо явно захватить J в динамике просто делаете в Context поле val type: KClass<out J>. Если в статике, никто не запрещает реификацию по двум параметрам
источник

AN

Alexander Nozik in Kotlin Community
Дошло
источник

AO

Alexey Otts in Kotlin Community
Igor Komarov
Но тогда получится что придется это писать для каждой обертки. В целом идея, но пока-что наверное остановлюсь на варианте с коротенькой функцией для создания kclass
Ну ещё есть вариант, если две скобки не испугают :peka:
источник

AN

Alexander Nozik in Kotlin Community
Danil Yudov
возвращаясь к мультиплатформенным либам. у меня есть зависимость на ktor-client, можно ли как-то настроить грэдл, чтоб он сам резолвил зависимость для конкретного sourceSet? а не писать для каждого по отдельности (а ля io.ktor:ktor-client-core-js, io.ktor:ktor-client-core-linuxx64)
да, это называется Gradle metadata, она в градлах новее 6.0 автоматом включена
источник