Mikhαil
Хз, мне нравится идея собирать самому - тогда ты знаешь что и зачем ты притащил. И тащишь зависимости по потребности. Да придётся все настроить - но тебе в норм проекте все равно придётся
Kirill
Mikhαil
Все эти темплейты - от лукавого для хелловорлдов
Mikhαil
Но мб я dead-perdead
Henry
Кстати, была статья на Хабре.
Henry
Henry
Для удовлетворения любопытства самое то.
Kirill
спс
Vasiliy
Критерий
это какие-то частные свёртки для разных типов
Doge
да как то неловко напрягать, мне просто любопытство удовлетворить
data Tree a = Leaf a | Branch (Tree a) (Tree a)
-- Обычный явный вариант, например для вычисления например суммы элементов:
sum (Leaf a) = a
sum (Branch left right) = (sum left) + (sum right)
-- И для вычисления глубины:
depth (Leaf a) = 1
depth (Branch left right) = 1 + max (depth left) (depth right)
-- тут нам явно пришлось писать рекурсивные функции, причем сама рекурсия в обоих функциях повторияется
-- а хотелось бы, чтобы можно было саму эту рекурсивную часть выделить отдельно и её переиспользовать
-- И тут нам на помощь как раз придут катаморфизмы
-- Теперь опишем необходимые нам вещи (они обычно в либах)
-- Тип, который позволит нам в дальнейшем описать рекурсивный тип на основе нерекурсивного
newtype Fix f = Fix { unFix :: f (Fix f) }
-- Непосредственно катаморфизм
-- Эта функция позволяет для любого рекурсивного типа отделить свертку и сам процесс рекурсии
-- При этом она обобщена как и по тому как мы сворачиваем, так и какой тип мы сворачиваем
cata :: Functor f => (f a -> a) -> (Fix f -> a)
cata alg = alg . fmap (cata alg) . unFix
-- Теперь описываем наш тип как нерекурсивный, заменяя все рекурсивные части на доп дженерик параметр
-- И создаем инстанс функтора для него
data TreeF a f = LeafF a | BranchF f f
deriving Functor
-- Теперь мы можем описать сумму и глубину, как нерекурсивную функцию вида TreeF Int Int -> Int
sumAlgebra (LeafF a) = a
sumAlgebra (BranchF left right) = left + right
depthAlgebra (LeafF a) = 1
depthAlgebra (BranchF left right) = 1 + max left right
-- И чтобы получить функцию мы воспользуемся библиотечными примитивами так, что в итоге нам явно рекурсию писать не придется
-- Аналогом исходного дерева будет такой синоним:
type Tree' a = Fix (TreeF a)
-- И чтобы получить сумму или глубину по такому дереву достаточно вызвать функцию cata + выше определнную sumAlgebra или depthAlgbera
sum' = cata sumAlgebra
depth' = cata depthAlgebra
Критерий
https://bartoszmilewski.com/2013/06/10/understanding-f-algebras/
Sergey
Doge
Alex
Alex
Anonymous
Vasiliy
Mikhαil
Тысячелетия прогресса чтобы в итоге опять к наскальной живописи прийти
Vasiliy
Vasiliy
имхо, когда то мы придем к тому чтобы писать иероглифами имхо
Mikhαil
Mikhαil
Так что это не имхо даже
Mikhαil
Ilya
Не от хорошей жизни разрешил.
Vasiliy
я не про китайский, а что уйдем от фонетики букв
Mikhαil
Mikhαil
Romɑn
https://twitter.com/mithridates/status/1399304617251405830?s=09
Ayrat
Короче, сидел писал, писал приложение. Решил подключить DI, потому что зависимостей уже стало много, ручками собирать заебался.
Раньше я работал с дубовым как полено Guice для джавы, он фичастый, но мне много не надо.
Сейчас решил попробовать kotlin-first experience - взял модный Koin
Вроде работает, но на CI тесты стали flaky, но хотя бы сразу понял что Koin говнит
Ayrat
так вот, эти педики в 2021 делают регистрацию в глобальный контекст даже если я делааю локальный
Ayrat
потому что нереализовано
Ayrat
То есть в одних тестах у меня один мок регается и стартуется этот ебучий Koin
в других тестах другой мок и стартуется этот Koin ещё раз (В ТОТ ЖЕ ИНСТАНС ЧТО И ПЕРВЫЙ БЛЯТЬ)
Ayrat
И кто успел мок зарегать, тот и папка
Ilya
Ayrat
Ayrat
Это как бы дефолт
Ayrat
если твои тесты не работают в многопотоке - иди в проституки сразу
Ilya
Ну естесна
У меня тоже был, но потом все таки пришлось отказаться в некоторых местах
Ayrat
Короче, нашёл я ишую, ей больше года, видимо никому кроме меня не нужны многопоточные тесты
Ayrat
Ayrat
Опасные ребята
это у меня такой закладывается. а эта хуита не умеет ни в какой параллелизм
Ayrat
потому что надо в одном классе отработать тесты с одними моками, потом в другой идти
Ayrat
я ж состарюсь
Ilya
Ayrat
Короче, придется откатывать эту хуиту и брать старый добрый Guice
пусть он и не модный
Ilya
Denis
... придётся откатывать этот котлин, и брать джаву, хоть она и не модная
Denis
😂😂
Denis
https://github.com/Kodein-Framework/Kodein-DI
вот еще есть
Denis
и там много всяких разных DI типо
Ayrat
Guice не то чтобы очень быстрый. Вот так бы я сказал. Но и далеко не самый медленный
Ayrat
Ayrat
Это вот к ебучей либе которая ебашит инстансы в глобальный контекст
Ilya
Ilya
Проплачено?😱
Igor
Ayrat
Ayrat
Ну почему люди такие говноеды.
вот тут типа специальный контейнер для теста с локальными оверрайдами создаётся.
на каждый тест или класс тестов такой можно создавать.
И вот в инстанс _koin кладётся вызов startKoin()
https://github.com/InsertKoinIO/koin/blob/master/core/koin-test-junit4/src/main/kotlin/org/koin/test/KoinTestRule.kt#L39
Который идёт в статичный глобальный контекст, и от него стартует Koin
https://github.com/InsertKoinIO/koin/blob/d9fdc2266d03ac64c6e7c3946046a052993d8dae/core/koin-core/src/jvmMain/kotlin/org/koin/core/context/GlobalContext.kt#L56-L60
ну просто нет слов насколько хуёво сделано.
Ayrat
бля -_-
Ilya
пащиму
Пропаганда депенденси реджекшн.
Ilya
Там боты в основной набежали, кстати. Можно тестить аватарки.
Ayrat
Хоспади какая же уёбская библиотека этот Koin
Щас будет немного боли и страданий.
Вот там короче есть модули, где можно объявлять свои депенденси. Вот как-то так
val testModule = module {
single { someService as SomeInterface }
}
я короче починил ебучую параллелизацию тем что скопировал из библы контексты и сделал его не синглтоном и создаю вообще всё с нуля для каждого теста.
Казалось бы, где может быть подвох?
А вот оказалось что когда контекст Koin грузит модуль в себя он в МОДУЛЕ проставляет флаг isLoaded (мутирует модуль, да)
И далее следующий контекст Koin берёт тот же инстанс модуля, чекает флаг и молча НЕ ГРУЗИТ ЕГО, т.к. блять if(module.IsLoaded) сука true
Я себе уже все волосы на мошонке вырвал от того что не понимал какого хуя ничего не работает. Ну пока вообще всё не передебажил на свете.
Ух блять, какой говноедский софт.
Ayrat
Ну понятно починю так
fun testModule() = module {
single { someService as SomeInterface }
}
то есть теперь на каждый контекст Koin будет ещё и модуль свой создаваться, их оказывается нельзя переиспользовать. Ебать идиотизм
Mark
сделай пр
Mark
спаси малюток
Ayrat
сделай пр
да там надо атомную бомбу засылать чтобы сжечь всё нахуй
Ayrat
у меня целый день горит уже
Ayrat
авторы сделали всё чтобы я не посмотрел сегдоня ютуб.
Ilya
А это разве не решение?
https://github.com/InsertKoinIO/koin/issues/613