@kotlin_lang

Страница 509 из 982
Igor
25.01.2018
15:17:15
Визитор может?
Эт не визитер. Визитер в другую сторону работает.

Руслан
25.01.2018
15:20:33
ну да, давно названия не повторял) interface EventHandler { fun onEvent(event: Event) { when (event) { is AddEvent -> onEvent(event) is RemoveEvent -> onEvent(event) } } fun onEvent(event: AddEvent) = default(event) fun onEvent(event: RemoveEvent) = default(event) private fun default(event: Event) { println(event) } }

конкретный сервис реализует интерфейс, имплеменит нужные onEvent'ы

получается простыня в EventHandler, но что поделать

Google
Dibro
25.01.2018
15:23:20
дак какая разница тогда?

Руслан
25.01.2018
15:23:54
Ну разница в том, что when только в одном месте?

Как было сказано - 100 ивентов всего, сервису интересны 10-20. В EventHandler простыня на 200 + C строк, в конкретном сервисе - просто вызовы методов/обработка

Если сервису нужно 10 ивентов - будет override 10 однострочников

раньше нужно было when распихать по всем сервисам

Ivan
25.01.2018
15:45:24
собирать все методы с аннотацией и генерить класс который внутри будет свитчить
ну в общем да, Ваш, @HeapyHop , метод вполне рабочий, даже круто что компилятор проверяет что все ли классы в свиче, но потом просто надоест поддерживать это руками и вернёмся к методу предложенному Dima способу (в реплае)

вообще меня изначально интересовало вообще это в байткоде можно сделать или нет

Руслан
25.01.2018
15:46:14
ну sealed класс будет умееть свитч по интам

так что будет быстро

Ivan
25.01.2018
15:46:54
ну sealed класс будет умееть свитч по интам
дада, я тоже уже об этом подумал

хотел сначала написать что медленно, но вспомнил Ваш коммент про sealed классы и инты

в джавке свитч по классам можно сделать разве только через class.getName()

а это жара с хешкодами

Google
Igor
25.01.2018
15:59:03
А тут anko-sqlite никто не использует? Не могу понять, оно experimental или уже нормальное и можно использовать?

Boris
25.01.2018
16:02:00
если кому-то интересно, чем кончилась моя котовасия к корутиноканалами, то вот: у меня был кейз (коммуникация с гитхабом), мне надо было сделать несколько поисковых запросов, резульаты склеить в один канал, отфильтровать, потом по каждому элементу из рузальтата сделать отдельный запрос (тут надо было распараллелить, чтобы значительно ускорить этот процесс) и чтобы на выходе получился канал в котором бы появлялись результаты по мере их получения. Я сделал для клиента корутиновый метод send, затем реализовал метод send, который возвращает канал в котором были значения по одному на каждую страницу резульатов, затем я добавил метд merge, который просто последовательно копировал в один канал элементы из всех суб-каналов, затем я добавил метод map идентичный натуральному, только с дополнительным парамером capacity который позволял расширить канал, потом внутри мапа я запускал запросы в потоки async, на выходе получился канал Deferred-ов, сделал метод который разворачивал дефереды селектом и складывал в канал дальше, на выходе я это всё фильтрую, дистиктю и отдаю из сервиса https://gist.github.com/fogone/e940de35f755c13299a65733c4b3be59

Сори за говнокод

Но суть я думаю передает

Sergey
25.01.2018
16:40:54
ReceiveChannel<T>.map так есть же такое в самой либе?

Boris
25.01.2018
16:42:00
Я же в описании написал

Что он идентичный, только можно capacity передать

Sergey
25.01.2018
16:44:54
а распаралеливание не делал еще?

Stas
25.01.2018
16:47:05
На нной итерации получится rx

Boris
25.01.2018
16:50:10
Просто распараллеливаются не все шаги, а только один

Мне так и надо было

См. fetchFullPrInfo

Kirill
25.01.2018
16:53:16
Не бейте за флуд только :)



Sergey
25.01.2018
16:53:28
хм, спс, наверное как раз то что надо мне

Boris
25.01.2018
16:54:47
Да, всё так ?

Конечно хотелось бы, чтобы хорошо проработанные средства для распараллеливания были из коробки, думаю это вопрос времени

Igor
25.01.2018
17:09:51
На нной итерации получится rx
А вот да. Кажется что на корутинах можно было и по проще написать, а не копировать рх

Google
Igor
25.01.2018
17:12:12
Вот ссылка на код есть, напиши
Чет лень и ты все равно будешь не доволен, тк не будет “рx-вого чейна”

Boris
25.01.2018
17:12:14
Я бы эталонным этот код не назвал, но даже и не смотря на это написать попроще боюсь не выйдет

Чет лень и ты все равно будешь не доволен, тк не будет “рx-вого чейна”
Так в том и дело, что хочется сделать и чтобы попроще и чтобы не выглядело куском дерьма, для этого хорошо подходят такие цепочки, но если ты знаешь как сделать тоже самое проще и не мне изящно, мне правда было бы интересно это увидеть

Чейн не самоцель, у него просто есть удобства, которые императивному походу не свойственны

Декларативность, хорошая модуляризация и гибкость в изменении отдельных шагов, краткость, хорошая расширяемость готовыми операциям

если и свои проблемы, конечно

Igor
25.01.2018
17:25:16
Имхо в RX единственное что важно тк его “поток событий”, который и отличает его от тех же промисов (те RX ~= Observable) А когда мы начинаем накручивать “бизнес логику” на операторах рx (или юзать Maybe/Single/Completable) - значит что где то мы свернули не туда.

Boris
25.01.2018
17:26:04
а где тут бизнес-логика? получить данные-то это бизнес-логика?

Igor
25.01.2018
17:26:29
Мердж, фильтрации и всякие хитрые объединения и изменение порядка

Boris
25.01.2018
17:28:07
а тоже самое в sql-е тебя не смущает? часто бизнес-логику в sql-е пишешь?

Igor
25.01.2018
17:29:08
Смущает конечно, но это уже не касается котлина и вообще это имхо.

Boris
25.01.2018
17:29:46
а это вопрос не котлина, это вопрос изоляции

к тому же это всё равно придется сделать в этом сервисе, цепочкой или нет

Ivan
25.01.2018
18:01:51
если кому-то интересно, чем кончилась моя котовасия к корутиноканалами, то вот: у меня был кейз (коммуникация с гитхабом), мне надо было сделать несколько поисковых запросов, резульаты склеить в один канал, отфильтровать, потом по каждому элементу из рузальтата сделать отдельный запрос (тут надо было распараллелить, чтобы значительно ускорить этот процесс) и чтобы на выходе получился канал в котором бы появлялись результаты по мере их получения. Я сделал для клиента корутиновый метод send, затем реализовал метод send, который возвращает канал в котором были значения по одному на каждую страницу резульатов, затем я добавил метд merge, который просто последовательно копировал в один канал элементы из всех суб-каналов, затем я добавил метод map идентичный натуральному, только с дополнительным парамером capacity который позволял расширить канал, потом внутри мапа я запускал запросы в потоки async, на выходе получился канал Deferred-ов, сделал метод который разворачивал дефереды селектом и складывал в канал дальше, на выходе я это всё фильтрую, дистиктю и отдаю из сервиса https://gist.github.com/fogone/e940de35f755c13299a65733c4b3be59
а как задача звучит совсем верхнеуровнево? Если без каналов и тому подобного?

Ivan
25.01.2018
18:02:41
у проекта? или у ряда проектов?

а, проекты?

или пулл-реквесты?

Boris
25.01.2018
18:04:25
пул-реквесты

да это по сути не так и важно

Google
Boris
25.01.2018
18:04:52
просто там целый флоу их получения

не просто запрос послать

поиском сначала ищутся пр-ы, потом по ним получаются детали

Ivan
25.01.2018
18:06:25
ну на входе получается список? Просто, насколько, я понял корутины-way - это написать последовательный код и дальше добавить саспенд модификаторов и соответствующих корутин-билдеров

Boris
25.01.2018
18:08:48
ну вот если каналами драйвить, то друой вей

см. код

выше

Andrew
25.01.2018
18:14:01
Вопрос по коду выше. В чём суть select с единственным .onAwait внутри? (метод `unwrap()`)

Boris
25.01.2018
18:14:09
@relizarov Роман, подскажите, есть вообще какие-то примеры такого использования каналов? планируется ли расширять библиотеку готовыми средствами для распараллеливания идущих по каналу потоков?

Konstantin
25.01.2018
18:20:52
@relizarov Роман, подскажите, есть вообще какие-то примеры такого использования каналов? планируется ли расширять библиотеку готовыми средствами для распараллеливания идущих по каналу потоков?
Тоже интересно + я бы еще дополнил вопрос о способах комбинирования и склеивания того, что в терминах rx называется hot и неизвестной длиной стрима.

Boris
25.01.2018
18:21:20
Вопрос по коду выше. В чём суть select с единственным .onAwait внутри? (метод `unwrap()`)
да ни в чем, это от моих экспериментов осталось, я так понимаю, что это будет работать так же как: fun <T> ReceiveChannel<Deferred<T>>.unwrap() = produce { consumeEach { send(it.await()) } }

тут надо было получать первый сыгравший, я начал это делать, но не добил

Andrew
25.01.2018
18:24:04
да ни в чем, это от моих экспериментов осталось, я так понимаю, что это будет работать так же как: fun <T> ReceiveChannel<Deferred<T>>.unwrap() = produce { consumeEach { send(it.await()) } }
Понял, я просто думал, что есть какое-то особенное поведение (пока так и не довелось использовать select самому). Тогда вроде как достаточно будет .map { it.await() }

Boris
25.01.2018
18:25:39
Понял, я просто думал, что есть какое-то особенное поведение (пока так и не довелось использовать select самому). Тогда вроде как достаточно будет .map { it.await() }
да. но это не совсем то поведение, которое я хотел получить, поэтому я оставил селект пока, чтобы еще поковырять

Sergey
25.01.2018
18:27:46
а нельзя сделать 1 канал на несколько акторов?

Andrew
25.01.2018
18:27:50
а нельзя сделать 1 канал на несколько акторов?
actor(...) сам создаёт канал, но в теории можно сделать свой аналог, принимающий его как параметр вместо capacity: https://github.com/Kotlin/kotlinx.coroutines/blob/ea4f2f3ac31ca7a4c80fd4afe7824b1ddf795c3c/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/channels/Actor.kt#L84

Boris
25.01.2018
18:43:46
а еще всё время хочется использовать generateSequence, но нельзя ?

Google
Boris
25.01.2018
18:44:42
причем buildSequnce тоже нельзя потому что в нем можно только его собственные саспенд-методы использовать

Sergey
25.01.2018
19:16:58
я так понимаю параллельная обработка выглядит примерно так?(если мне нужно в одном потоке это делать) runBlocking { val channel = Channel<Int>() launch { for (i in 0..20) { channel.send(i) } channel.close() } (0..4) .map { i -> launch(Unconfined) { channel.consumeEach { delay(2000) val thread = Thread.currentThread().name println("$thread: i=$it coroutine=$i") } } } .forEach { it.join() } }

Andrew
25.01.2018
19:27:00
По идее первый channel.consumeEach выгребет все данные и все i от 1 до 4 ничего не получат.

Sergey
25.01.2018
19:28:30
ну оно работает)

Andrew
25.01.2018
19:29:18
Да, delay же точка саспенда. Логично.

Sergey
25.01.2018
19:30:21
даже если убрать delay то будет работать

Andrew
25.01.2018
19:34:01
ChannelIterator.next(): > Retrieves and removes the element from this channel suspending the caller while this channel isEmpty [...] По идее ж канал не должен успевать быть пустым. Теперь мне интересно, почему это работает, присоединюсь к ожиданию ответов.

Переключение ведь происходит не на каждом вызове suspend fun, верно?

Boris
25.01.2018
19:35:44
У меня есть прототип метода, который получает деферы по мере из выполнения, он получает все что есть в канале и пытается селектить из всех них, когда значение приходит он его из пула удаляет и повторяет селект

Но это почему-то не работает

Все что есть, в смысле все что доступно

Это обычно < capacity

Stas
25.01.2018
19:44:53
вброс: зачем вообще корутины, если есть rx?

Igor
25.01.2018
19:46:45
Народ так завелся паралельными флоу - что я уже и не знаю ?

Boris
25.01.2018
19:47:32
вброс: зачем вообще корутины, если есть rx?
Так рх не саспендится же, а так я прямо в этом флоу вызываю саспенд методы запросов

Stas
25.01.2018
19:48:40
саспенд внутри на тредлупе работает7

Boris
25.01.2018
19:49:39
Как асинхронный запрос в клиенте реализован это уже другой вопрос

Artem
25.01.2018
19:49:43
Ребята, а может кто-то коротко и толково изложить, что есть это "suspend"? А то я не очень понимаю

Boris
25.01.2018
19:51:06
Ребята, а может кто-то коротко и толково изложить, что есть это "suspend"? А то я не очень понимаю
Это такое место в методе где выполнение можно остановить и продолжить в любой момент

С того места где остановился

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