Написал маленькую заметку о том, как настроить отправку писем с обновлениями RSS-каналов себе на почту. Бесплатно, без смс и сторонних сервисов.
chugunkov.website
Отправка обновлений RSS на email своими руками
Гайд по настройке собственного rss-клиента, отправляющего новые статьи на почту
Только недавно обнаружил удобный способ объединить последние коммиты в гите.
После долгой работы в локальной ветке возникает последовательность коммитов вида:
Сплющивание делается элементарной командой
После долгой работы в локальной ветке возникает последовательность коммитов вида:
f6e1600 - фикс опечаткиВесь этот мусор хорошо бы сплющить в один коммит с вменяемым названием перед тем, как отправлять в общий репозиторий.
f5e6e43 - исправление компиляции
dade538 - исправление таймаута
2465e49 - форматирование
903f37d - реализована [название большой задачи]
Сплющивание делается элементарной командой
git reset --soft HEAD~X
X — количество мусорных коммитов. После этого делаем git commit и прописываем нормальное сообщение. Этот способ гораздо более удобный и идиоматичный, чем git rebase -i, который я использовал раньше.Решил поиграться с dotty (прототип Scala 3) и выразил монадные трансформеры через
Трансформеры на них выглядит классно, но боюсь, что в рантайме создаются лишние объекты из-за
Само собой, побенчмаркал сравнение с классической на данной момент реализацией через
Говнокод тут
opaque types. Это такие алиасы для типа, которые работают как алиасы только в скоупе своего определения, а в других местах компилятор воспринимает их как полноценный самостоятельный тип. А ещё поговаривают, что их завезут уже в 2.13!Трансформеры на них выглядит классно, но боюсь, что в рантайме создаются лишние объекты из-за
implicit class, не наследующего AnyVal.Само собой, побенчмаркал сравнение с классической на данной момент реализацией через
case class. EitherT c Try работает примерно на 15% быстрее классической реализации, а OptionT — на 30. Если использовать Future, то разницы практически нет. (мои замеры кривые и им нельзя доверять)Говнокод тут
Жирное обсуждение на реддите о том, что в Haskell удобнее, чем в Scala.
В тред ворвались мастодонты обоих сообществ: Edward Kmett и Sam Halliday со стороны Haskell и Alexandru Nedelcu с Wojtek Pituła на защите скалы 🍿
В тред ворвались мастодонты обоих сообществ: Edward Kmett и Sam Halliday со стороны Haskell и Alexandru Nedelcu с Wojtek Pituła на защите скалы 🍿
reddit
Ok, I'll bite. What does Haskell do better than Scala?
This is a *serious* question. Obviously, if people "ascend" to Haskell, there must be a good reason. I'd like you to tell me these reasons. What...
Написал в бложик про создание пакетов для Arch Linux, медленный запуск программ на скале и причём тут GraalVM.
TL;DR делать пакеты для арча весело и стильно, а вовсе не сложно
TL;DR делать пакеты для арча весело и стильно, а вовсе не сложно
chugunkov.website
Создание пакета для Arch Linux
Гайд по созданию пакета для Arch Linux на примере утилиты scalafmt
Бинго для доклада на конференции по ФП:
> pure functions
> immutable data structures
> avoid impurity
> aaaaaaand... it's composable!
> monad
> side effects
> state
> *показывает hello world в репле*
> pure functions
> immutable data structures
> avoid impurity
> aaaaaaand... it's composable!
> monad
> side effects
> state
> *показывает hello world в репле*
Только сейчас наткнулся на пакет errors для голанга, который добавляет в язык почти эксепшены. Только с маааааленьким нюансом: стэктрэйс составляет не рантайм языка, а программист. Элегантное решение!
Давно подслушал и недавно осмыслил простое, но полезное правило использования тайпклассов в Scala.
Допустим, вы пишите полиморфное хранилище ключ-значение и хотите иметь возможность получить все значения в отсортированном виде:
Благодаря гранулярности требований достигается универсальность интерфейса.
Допустим, вы пишите полиморфное хранилище ключ-значение и хотите иметь возможность получить все значения в отсортированном виде:
abstract class KeyValueStorage[T: Order] {
def get(id: String): T
def put(entity: T): Unit
def delete(id: String): Unit
def sorted(): List[T]
}
Для того, чтобы значения типа T могли быть отсортированы, на него накладывается требование Order. Но фактически это требование нужно для реализации только одного метода из четырёх — sorted. Поэтому его можно локализовать:trait KeyValueStorage[T] {
def get(id: String): T
def put(entity: T): Unit
def delete(id: String): Unit
def sorted()(implicit O: Order): List[T]
}
Теперь пользователи могут использовать реализации этого хранилища для объектов, которые нельзя сравнивать. Компилятор не позволит им вызвать метод sorted, но остальные методы будут доступны.Благодаря гранулярности требований достигается универсальность интерфейса.
Градация программистов здорового человека от Basecamp:
* до 2 лет опыта — Junior Programmer
* 2-5 лет — Programmer
* 5-8 лет — Senior Programmer
* 8-12 лет — Lead Programmer
* 12+ лет — Principal Programmer
И откуда-то со дна стучит СНГ-шное айти:
«Здравствуйте))) Нам очень понравилось ваше резюме на полгода опыта, хотим предложить вам позицию сеньор биг дата архитектора 💅👨🏻💻 в перспективной компании...»
«Team Lead в 19 лет: невероятная история программ...»
«С нуля до старшего разработчика за 21 день. Надо всего лишь...»
* до 2 лет опыта — Junior Programmer
* 2-5 лет — Programmer
* 5-8 лет — Senior Programmer
* 8-12 лет — Lead Programmer
* 12+ лет — Principal Programmer
И откуда-то со дна стучит СНГ-шное айти:
«Здравствуйте))) Нам очень понравилось ваше резюме на полгода опыта, хотим предложить вам позицию сеньор биг дата архитектора 💅👨🏻💻 в перспективной компании...»
«Team Lead в 19 лет: невероятная история программ...»
«С нуля до старшего разработчика за 21 день. Надо всего лишь...»
Раньше я думал, что меня сложно удивить, но тут человеку, отправившему pull request с исправлением опечатки, предлагается распечатать и подписать лицензионное соглашение.
При этом библиотека открытая и опубликована под лицензией Apache-2.0.
Само собой PR висит уже больше года, а опечатка как была в исходниках, так и осталась.
При этом библиотека открытая и опубликована под лицензией Apache-2.0.
Само собой PR висит уже больше года, а опечатка как была в исходниках, так и осталась.
Написал небольшой пост про то, как я переписал
TL;DR это действительно так работает, но бежать переписывать прод на циклы смысла нет
foreach на while в своей скала-либе и получил прирост производительности почти в два раза.TL;DR это действительно так работает, но бежать переписывать прод на циклы смысла нет
chugunkov.website
Микрооптимизация scala-phash
Оптимизация Scala кода с помощью замены map и foreach на циклы while
В интервью Кирилла Мокевнина с Романом Павлушко (бывший CTO Avito) услышал, что у них есть слак-бот, которому можно дать описание сервиса «голанг, два редиса, постгрес», и он автоматически создаст репозиторий с шаблоном проекта, докер образ, развернёт нужную инфраструктуру и позволит задеплоить это на прод в одно нажатие кнопки.
По этому поводу могу сказать только одно слово: ХОТЕТЬ
По этому поводу могу сказать только одно слово: ХОТЕТЬ
Отличная заметка от Daniel Spiewak про использование тред-пулов в jvm.
1. Если задачи грузят преимущественно CPU (например, распараллеленные числодробилки), брать пул с фиксированным количеством тредов. Тредов столько же, сколько и ядер в процессоре:
3. Для асинхронных операций брать
От себя добавлю, что поверх этих тред-пулов должно исполняться исключительно моднейшее ZIO с тремя дырками!
1. Если задачи грузят преимущественно CPU (например, распараллеленные числодробилки), брать пул с фиксированным количеством тредов. Тредов столько же, сколько и ядер в процессоре:
newFixedThreadPool(Runtime.getRuntime.availableProcessors)
2. Для блокирующего i/o нужен пул, который умеет плодить много потоков. cachedThreadPool с этим отлично справится.3. Для асинхронных операций брать
forkJoinPool и не забивать его никакими задачами, кроме, непосредственно управления исполнением программы.От себя добавлю, что поверх этих тред-пулов должно исполняться исключительно моднейшее ZIO с тремя дырками!
Gist
thread-pools.md
GitHub Gist: instantly share code, notes, and snippets.
Интересный доклад Андрея Паньгина с развенчанием мифов о «медленной» jvm в сравнении с C++. Сравниваются решения типичных для бэкендов задач: сетевое и файловое i/o, мультитрединг, числодробление. Правда замеры выглядят слегка предвзятыми 🙈
Проблема этого доклада в том, что после его просмотра возникает сильное желание читать статьи про структуру кучи в jvm, устройство HotSpot и tiered compilation.
Проблема этого доклада в том, что после его просмотра возникает сильное желание читать статьи про структуру кучи в jvm, устройство HotSpot и tiered compilation.
YouTube
Андрей Паньгин — Мифы и факты о медленной Java
Подробнее о Java-конференциях:
— весной — JPoint: https://jrg.su/gTrwHx
— осенью — Joker: https://jrg.su/h7yvG4
— —
. . . . Андрей Паньгин — Мифы и факты о медленной Java
Java-конференция Joker 2016, Санкт-Петербург, 14-15.10.2016
Встречайте специальный…
— весной — JPoint: https://jrg.su/gTrwHx
— осенью — Joker: https://jrg.su/h7yvG4
— —
. . . . Андрей Паньгин — Мифы и факты о медленной Java
Java-конференция Joker 2016, Санкт-Петербург, 14-15.10.2016
Встречайте специальный…
Привет подписчикам от профункторного коллеги👽
Если кто-то до сих пор не знает, что же такое, собственно, profunctor optics, есть хорошая серия статей с объяснением (осторожно, МАТЕМАТИКА!)
Если кто-то до сих пор не знает, что же такое, собственно, profunctor optics, есть хорошая серия статей с объяснением (осторожно, МАТЕМАТИКА!)
Для того, чтобы убрать файл из индексации гита обычно используется
В гитигнор я обычно прописываю те файлы, которые обязательно появятся у всех, кто работает над проектом:
.gitignore. Но есть ещё одна возможность скрыть файлы — .git/info/exclude. В отличие от .gitignore он не шарится вместе с остальным проектом, а хранится локально.В гитигнор я обычно прописываю те файлы, которые обязательно появятся у всех, кто работает над проектом:
target/А в
project/target/
exclude то, что связано с моим личным окружением и не интересно никому, кроме меня:.metals/
.bloop/
magic-script-with-benchmarks.sh