Читать в телеге. Когда-то там были посты не только от меня.
Контракты в Kotlin
Недавно наткнулся на случай, когда они пригодились. Рассмотрим пример:
data class OptionalResult(val data: Payload?, val someFlag: Boolean)
fun OptionalResult?.getData(): Payload {
this ?: throw NoResultException()
return this.data ?: throw NoPayloadException()
}
fun someFun(){
val payload: Payload = getResult().getData()
doStuffWithPayload(payload)
if (payload.someFlag){ //oopsie
// do more stuff
}
...
}
По сути имеем дважды опциональный результат, и в ФП-парадигме это красиво легло бы в мона.. Option, но у нас Kotlin с исключениями.
Однако строка с oopsie
вызовет ошибку компиляции, т.к. компилятор не понимает, что payload уже был проверен на null
.
Причем если тело функции подставить вместо вызова, то все будет ок (ссылочная прозрачность плачет в уголочке).
Чтобы решить проблему, можно использовать контракты и явно сказать компилятору, что если функция что-то вернула, то ее аргумент — не null
:
fun OptionalResult?.getData(): Payload {
contract {
returns() implies (this@getData != null)
}
this ?: throw NoResultException()
return this.data ?: throw NoPayloadException()
}
В общем, фича интересная, но, кажется, компилятору стоит быть поумнее.
Запуск команды без пароля sudo
Лучше такой пост, чем никакой, наверно :/
- Создаем исполняемый скрипт. Его нужно создать через sudo, чтобы нельзя было редактировать. Иначе это будет дырищей, через которую можно будет запускать что угодно.
sudo nano /usr/sbin/some_command
# добавляем shebang и саму команду
# ...
sudo chmod +x /usr/sbin/some_command
- Добавляем настройку через
sudo visudo
, обязательно в конец файла.
some_user ALL=(ALL) NOPASSWD: /usr/sbin/some_command
some_user
— имя пользователя.
- Теперь можно запускать команду через
sudo some_command
, и пароль не будет запрашиваться. Можно повесить на хоткей какой-нибудь.
Мне пригодилось для того, чтобы рестартовать демон частоты процессора. Ноут почему-то периодически решает, что 400 MHz хватит всем, почему — быстро не докопался, поэтому решил костылем.
Составные шаблоны индексов в Elasticsearch
Оказывается, уже давненько в Elasticsearch можно собрать шаблон индекса по кусочкам, причем их можно переиспользовать — например, какие-нибудь преобразования текста типа стемминга вынести в общий кусочек. Долой копипасту!
Исключение файлов без расширения в .gitignore
В дополнение к предыдущему посту — занятная проблемка.
По умолчанию go build
генерирует исполняемый файл прямо в корень проекта (sic!).
Исполняемый файл в репозитории мы не хотим хранить, и чтобы его исключить, обычно делают Makefile (еще один прекрасный язык, кстати) или добавляют в .gitignore название проекта.
Но есть способ поинтереснее:
*
!/**/
!*.*
Тут сначала игнорируются все файлы, потом с помощью отрицания (!
) разрешаются все файлы внутри папок и все файлы, имеющие расширение.
Правда, отвалится Dockerfile
, но у него хотя бы имя фиксированное.
Еще один шанс для Go
По работе надо было написать микросервис для перекладывания JSON’ов, решил дать еще один шанс языку Go и написать на нем, с разбором впечатлений, как для Elm или Rust. Микросервис-то я написал, а вот пост писать раздумал, решил ограничиться примером, который, как мне кажется, довольно показательный.
Вот у нас есть метод из стандартной библиотеки, log.Fatal
. Что он делает?
Ответ
Ожидаемый ответ — выводит сообщение в лог с уровнем FATAL. Сообщение он действительно выведет. Но еще он и завершит программу с кодом возврата 1. А я еще студентам пытаюсь что-то про SRP и хорошие имена говорить…
Ок, а что делают log.Info
и log.Error
?
Ответ
Ошибку компиляции делают, потому что нет таких методов.
Тренажер сисадмина
Приезжает дальнобойщик домой, думает, в какую бы игру залипнуть для расслабона — Euro Truck Simulator, каеф!
Если не хватает подобного для решения проблем в Linux — есть игруля. Задания не очень сложные, местами жизненные. Если непонятно, что делать, то есть подсказки и можно даже какие-то команды новые узнать.
Бонус для ИБшников и прочих хакеров — вам дают рутовый доступ к временному контейнеру в AWS, RCE as a Service, налетай!
Настройки JVM
Подробный сборник всех опций популярных JVM с поиском и значениями по умолчанию.
Текущие проблемы с потоками и асинхронщиной
Неплохой доклад про текущее состояние асинхронного выполнения задач в JVM, хоть и очень тезисный.
Вначале немного повторения кэши L1-L3 и устройство процессора в целом, про потоки, очередь задач и их конкурентное выполнение, переключение контекста. Потом внезапно переключается на JVM — каждый поток это корень для сборщика мусора. Чем больше потоков, тем медленнее он работает. Какой-нибудь FixedThreadPool не решает проблемы, т.к. у него случайный порядок выполнения.
Далее — основы асинхронного выполнения и epoll. “Многие из вас плохо читают на C, поэтому я перевел этот кусок кода на Scala”:) Как решить проблему, что потоки ничего не делают, пока ждут? Перекинуть все ожидание на 1 поток. Но даже это дороговато. Эту проблему решили в nodejs-ной библиотеке libuv, которая в одном потоке и полезную работу делает, и ждет IO.
В идеальном мире на каждом ядре работает только один поток, одна задача по максимуму выполняется на своем потоке, чтобы все было хорошо с кэшами. А еще это все спрятано от прикладного программиста. Системы эффектов близки к этому, они хорошо решают проблему управления задачами, но все разбивается о нижележащие библиотеки для работы с потоками.
Sed и разделитель
Оказывается, в sed
можно использовать почти любой разделитель, т.е. эти варианты
sed -i 's/Hello/Goodbye/g' input
sed -i 's%Hello%Goodbye%g' input
sed -i 's Hello Goodbye g' input
sed -i 'ssHellosGoodbyesg' input
будут работать одинаково. В качестве разделителя используется первый символ после s
. Увы, прокатит только однобайтный символ, Ы
не подойдет.
Спонсор это минутки — Ярослав:)
Пофлексить
Интерактивный туториал по основам FlexBox.
В начале порадовала аналогия с шашлыком (главная ось = шампур, элементы = мясо).
А ближе к концу расстроило понимание, что вроде хотели все упростить по сравнению со “обычным” стилем, а получилось как всегда.