@kotlin_lang

Страница 847 из 982
Andrey
04.09.2018
08:48:12
принять лямбду в метод и отправить ее в глобал это нормально?
Лямбда - частный, специально организованный случай объекта. Нормально ли для функции принять объект и сохранить его в статике? Всё зависит от того, что за объект, и с какой целью его сохраняют. Уточните ваши обстоятельства.

Maxim
04.09.2018
08:51:55
Глобальное изменяемое состояние? Идём рефакторить.
никто не говорил про изменяемость, но даже глобальное изменяемое состояние - вещь вполне правильная в некоторых случаях

Google
Andrey
04.09.2018
08:52:46
Нет. Абсолютно ненормально.
Ну почему же? Если это часть DI библиотеки - вполне себе вариант для построения дерева зависимостей.

Quantum Harmonizer
04.09.2018
08:52:56
Ну почему же? Если это часть DI библиотеки - вполне себе вариант для построения дерева зависимостей.
Тогда получится, что разные модули не могут её безопасно использовать и будут влиять друг на друга.

Andrew
04.09.2018
08:56:48
Тогда получится, что разные модули не могут её безопасно использовать и будут влиять друг на друга.
Если изменения атомарные, почему нет? Даже Kotlin/Native такое позволяет, где за основу взято mutable^shared.

Andrey
04.09.2018
08:56:48
Тогда получится, что разные модули не могут её безопасно использовать и будут влиять друг на друга.
Нет, не получится. Это вопрос реализации библиотеки. Глобальное состояние не значит непосредственно доступное всем. Его можно сделать доступным только для самой библиотеки, а она будет решать, как им рулить. В конце концов, у нас любое JVM приложение начинается с глобального (в пределах класс лоадера) изменяемого состояния загруженных классов.

Andrey
04.09.2018
08:58:33
Потому что глобальное — непредсказуемо, нетестируемо. Нечисто.
Да, но у любом языке есть нечистое глобальное IO как минимум.

Загруженные классы можно рассматривать как кэш. Свежезагруженный класс отличается от загруженного месяц назад только производительностью.
Ну так я и говорю, что для кэширования норм. При этом сам кэш - глобальное изменяемое состояние. Я потому и сказал, что надо цели уточнить.

Quantum Harmonizer
04.09.2018
08:59:49
Andrey
04.09.2018
09:00:56
Да, но к нему отношение особое. Кеширование/мемоизация — не такие уж сайд-эффекты.
Ну опять же, я вижу смысл сохранения лямбд куда-то для целей кэширования.

Anton
04.09.2018
10:06:21
тут недавно были вопросы по поводу конфликтов имен с екстеншен функциями. к чему пришли в итоге?

Konstantine
04.09.2018
10:12:17
Уже вроде говорилось, но я забыл. Говорили, что корутины у нас доступны из коробки и ими можно пользоваться без доп. либы. Как я могу запустить что-то в виде корутины в андроеде не используя либу?

Google
Руслан
04.09.2018
10:15:32
Andrew
04.09.2018
10:15:59
Уже вроде говорилось, но я забыл. Говорили, что корутины у нас доступны из коробки и ими можно пользоваться без доп. либы. Как я могу запустить что-то в виде корутины в андроеде не используя либу?
Ну ты опять за своё? https://github.com/Kotlin/kotlinx.coroutines/blob/master/ui/kotlinx-coroutines-android/src/HandlerContext.kt Берёшь и копипастишь в свой код. Вжух — и у тебя нету либы. В компиляторе заложен базовый минимум, без которого жить нельзя, всё остальное живёт в kotlinx.coroutines. Без неё можно жить, дублируя всё, что в ней есть, но зачем?

Руслан
04.09.2018
10:21:16
Igor
04.09.2018
10:25:08
Руслан
04.09.2018
10:26:33
сначала захочется launch и runBlocking, потом withContext, потом окажется что exceptions нужно как-то там обрабатывать и в итоге будет куча плохо оттестированных велосипедов.

Igor
04.09.2018
10:27:50
Вот что действительно растраивает, что IO/DefaultDispatcher есть в core, а вот UI для каждую платформу отдельный (хотя тот же DD может подбирать поаьформенную реализацию в рантайма)

Vlad
04.09.2018
10:44:04
https://twitter.com/asolntsev/status/1036602457185570817

Andrey
04.09.2018
10:46:46
https://twitter.com/asolntsev/status/1036602457185570817
Странная идея брать и всё переписывать. Я понимаю, если что-то новое реализовывать с использованием новых инструментов, но переписывать то, что уже работает... А кто платит за эти трудозатраты и связанные риски?

Руслан
04.09.2018
10:51:07
А в соседней команде Антон Кекс успешно заадоптил Котлин)

Andrey
04.09.2018
11:02:39
Обнаружил тут небольшую проблемку в выведении типов при взаимодействии Kotlin с Java 8 Streams: fun main(args: Array<String>) { val map = listOf(1, 2, 3).stream() .map { it to it * 2 } .collect(Collectors.toMap({ it: Pair<Int, Int> -> it.first }, { it.second })) // так работает val map1 = listOf(1, 2, 3).stream() .map { it to it * 2 } .collect(Collectors.toMap({ it.first }, { it.second })) // почему-то не может вывести, что ключ мапы Int } Нитересно, почему он не может вывести тип ключа мапы без подсказки?

Igor
04.09.2018
11:02:56
Мне бы наоборот, унечти UI в кор, что бы легко (интеграционные) unit тест писать

?Kolay
04.09.2018
11:04:56
А что будет работать быстрее? UI/IO

Google
Andrey
04.09.2018
11:11:16
val pair = 1 to 1 val map2 = Collectors.toMap({ pair.first }, { pair.second })
Нет, это другое. Тут он ме может вывести тип аргумента передаваемых лямбд

А что вообще значит такое объявление? public static <T, K, U> Collector<T, ?, Map<K,U>>
Дженерик функция, с тремя параметризуемыми типами T, K и U, возвращающая Collector, параметризованный T, не важно чем, Map<K, U>

Руслан
04.09.2018
11:13:42
Я про вопросик конечно

Andrey
04.09.2018
11:14:04
Я про вопросик конечно
? то же самое, что * в Kotlin

Руслан
04.09.2018
11:14:35
ну вот тут тип не прокидывается, как котлин может вывести тип аккумулятора тут?

в джаве 10 с var работает?

Andrey
04.09.2018
11:15:54
ну вот тут тип не прокидывается, как котлин может вывести тип аккумулятора тут?
Так ему дано указание: не выводи тип аккумулятора, пофиг что там. * короче

Руслан
04.09.2018
11:16:05
ну так вот и не выводит)

Andrey
04.09.2018
11:16:47
ну так вот и не выводит)
Он не выводит не это. Он не выводит тип ключа результирующей мапы. K который.

dimiii
04.09.2018
11:25:47
Andrey
04.09.2018
11:28:57
Понял, это всё от variance. Без явного указания типа аргумента лямбды, он не может понять, это Pair<Int, Int> или кто-то из её предков, а без этого он не может вывести тип результата выражения it.first

dimiii
04.09.2018
11:29:03
К - консистентность >>> val f = { it } error: unresolved reference: it val f = { it }

Andrey
04.09.2018
11:30:30
dimiii
04.09.2018
11:30:46
Andrey
04.09.2018
11:31:22
Ну это понятно )
Ну а где он возьмёт it, если ему не известен тип лямбды?

dimiii
04.09.2018
11:32:06
Ну а где он возьмёт it, если ему не известен тип лямбды?
Я к тому, что этот corner case просто должен толковаться в пользу identity function

Andrey
04.09.2018
11:33:43
Я к тому, что этот corner case просто должен толковаться в пользу identity function
it в Kotlin - сахарок для лямбд от одного аргумента, а тут не ясно, один у неё аргумент, два, ноль или сколько. Это же не Haskell, где все лямбды от одного аргумента (каррированные)

Я к тому, что этот corner case просто должен толковаться в пользу identity function
В Котлине вообще нельзя объявить identity lambda как val, чтобы при этом не потерять вывод типов. <T> val identity: (T) -> T нельзя, так как не поддерживаются полиморфные значения. Дженерик полиморфизм только для функций и классов.

Andrey
04.09.2018
11:42:58
По-моему, как раз с этим были связаны твои первые посты в этом чатике. Вроде бы ты даже нашел какой-то трюк с type-aliases. Нет?
Не, тут никаких трюков быть не может особо. Полиморфные значения или есть в системе типов, или нет. Если нет, никак их не заменишь.

Google
Quantum Harmonizer
04.09.2018
11:43:32
У меня вообще есть object Just : (Any?) -> Any?, который я не стесняясь кастю во что попало.

dimiii
04.09.2018
11:43:50
Ну спасибо, хоть для функций оставили

Andrey
04.09.2018
11:44:42
В Котлине система типов мономорфная, то есть тип значения не может содержать дженериков, объявленных для самого значения.

Вот так можно, чтоб не засорять лишними лямбдами кучу: private val id: (Any?) -> Any? = { it } // определяем id лямбду fun <T> id(): (T) -> T = id as (T) -> T // говорим компилятору: "верь мне, я инженер, можешь кастить"

Quantum Harmonizer
04.09.2018
11:48:36
fun <T> id() = { it: T -> it } думаю, эффект будет точно такой же

Andrey
04.09.2018
11:49:09
fun <T> id() = { it: T -> it } думаю, эффект будет точно такой же
Нет, здесь при каждом вызове новая лямбда создаётся

Admin
ERROR: S client not available

Quantum Harmonizer
04.09.2018
11:50:00
Andrey
04.09.2018
11:52:49
Нет, только что проверил.
Да, сейчас действительно не создаётся. Значит в одной из предыдущих версий так было.

Нет, только что проверил.
Я, похоже, спутал с более хитрым случаем: если пытаться реализовать комбинаторы на Котлине, то identity выражается через S и K комбинаторы, как S(K)(K), и вот при таком выражении, у нас на каждый вызов identity создаётся новый объект: import java.lang.System.identityHashCode fun main(args: Array<String>) { val iInt: I<Int> = i() val iStr: I<String> = i() println(identityHashCode(iInt)) println(identityHashCode(i<Int>())) println(identityHashCode(iStr)) println(iInt(1)) println(iStr("a")) } typealias K<A, B> = (A) -> (B) -> (A) fun <A, B> k(): K<A, B> = { a -> { a } } typealias S<A, B, C> = ((A) -> (B) -> C) -> ((A) -> B) -> (A) -> C fun <A, B, C> s(): S<A, B, C> = { x -> { y -> { z -> x(z)(y(z)) } } } typealias I<A> = (A) -> A fun <A> i(): I<A> = s<A, Any?, A>()(k())(k<A, Any?>()) Выводит 1818402158 1590550415 1058025095 1 a

Quantum Harmonizer
04.09.2018
13:01:55
Ой, какая жесть. Ну, там присутствует захват, это решающий фактор.

Andrey
04.09.2018
13:07:59
Ой, какая жесть. Ну, там присутствует захват, это решающий фактор.
Я помнимаю, что это связано с захватом внешнего контекста, но если бы s, k и i были не функции, а полиморфные значения, то i было бы всегда одним значением.

Quantum Harmonizer
04.09.2018
13:08:30
Я не ФПшник, я джавист. Непонимат.

Andrey
04.09.2018
13:09:57
Я не ФПшник, я джавист. Непонимат.
Вот у нас есть fun <A> i(): I<A> Почему бы в языке не быть val <A> i: I<A>

Quantum Harmonizer
04.09.2018
13:10:41
Вот у нас есть fun <A> i(): I<A> Почему бы в языке не быть val <A> i: I<A>
Ну это я понимаю, да. О такой штуке не раз думал.

Alexey
04.09.2018
13:11:56
Ну вообще тут как раз понятно почему, потому что в языке не все объекты есть функция

Andrey
04.09.2018
13:12:30
Ну это я понимаю, да. О такой штуке не раз думал.
Ну так я и проиллюстрировал, правда на синтетическом примере, когда без этого придётся или создавать лишние объекты, или кастить.

Alexey
04.09.2018
13:13:02
<T> HashMap<Class<T>, T> не менее полезен)
И какое у этого должно быть поведение?

Или у вот такого? val <A> foo = listOf<A>()

Google
Quantum Harmonizer
04.09.2018
13:13:58
И какое у этого должно быть поведение?
get(K): V? становится <T> get(Class<T>): T?

Alexey
04.09.2018
13:14:55
get(K): V? становится <T> get(Class<T>): T?
Если какой либо компилятор сможет это, его можно смело в битву экстасенсов отправлять

Quantum Harmonizer
04.09.2018
13:15:14
не, оно решимо, просто бестолково (из-за примера с листом)

Andrey
04.09.2018
13:15:45
Ну вообще тут как раз понятно почему, потому что в языке не все объекты есть функция
А как это связано вообще с дженерик полиморфизмом? Ну да, функция - частный случай объекта (хотя и любой объект можно выразить как функцию конструктор, которая возвращает функцию диспетчер методов объекта). При чём тут полиморфные значения?

Quantum Harmonizer
04.09.2018
13:19:53
вот кстати, нет типа, который позволяет выразить fun <T> invoke(t: T): ...

то есть, когда такое нужно, хоть SAM-интерфейс пиши

Alexey
04.09.2018
13:20:22
А какой тип справа?

Andrey
04.09.2018
13:20:47
Полиморфизм возможен только на функциях
Это ещё почему? Вот есть у нас пустой список. Он полиморфен по типу, которым параметризуется. То есть он один, пустой, поэтому не важно, список чего это.

Список, это 100% не функция

Alexey
04.09.2018
13:21:10
Он не полиморфен

Он контрвариантен

Quantum Harmonizer
04.09.2018
13:21:22
А какой тип справа?
неважно, тут дело в дженерике, а там может быть хоть () -> Unit

Alexey
04.09.2018
13:22:34
неважно, тут дело в дженерике, а там может быть хоть () -> Unit
Вообще что угодно можно выразить через лямбу, так что где то ты тут лукавишь :)

Страница 847 из 982