-
Новый макбук
Похвастаюсь, что ли, обновкой — прикупил новый макбук! Хоть старый и откачали, решил воспользоваться поводом: давненько хотел обновить железку.
Скажу сразу, что обзорщик железа из меня — примерно как бьюти-блогер. Не будет картинок и “продакшена”. Этот пост — попытка сказать о маках то, что мне кажется важным.
Новый мак интересен тем, что он кастомный: у него экран с нанотекстурой. Дело в том, что мне нравятся матовые экраны. Дело вкуса, и я за это не топлю, просто нравится. Кто-то гонится за герцовкой, кто-то за матрицей, а мне нужен матовый экран.
Мой первый ноут Thinkpad x220i потому и покорил мое сердце, что был матовым. Я искренне не понимаю, как можно смотреть в экран, который на две трети отражает все вокруг. Я хочу экран, а не зеркало.
Конечно, везде написано “антибликовое покрытие”, но это ерунда — оно бликует и отражает.
Эпл так сильно любит пользователей, что не оставляет им выбора. На всех маках стабильно был глянец, но лет пять назад ситуация поменялась. Эплы выпустили огромный 6К-монитор за пять косарей; за лишний косарь можно было сделать поверхность матовой за счет нанотекстуры (а за еще один косарь — купить ногу-подставку).
Что это за нанотекстура такая? Прежде чем ответить, вспомним, как устроен матовый экран. Это обычный глянцевый экран, на который наклеена шершавая пленка. Из-за неровности она рассеивает свет, и получается матовый эффект. Пленка немного скрадывает яркость и угол обзора; ее можно отодрать и получить обычный глянцевый экран.
Эпл добился того же эффекта, но более сложным путем. С помощью лазера на стекле выжигают миниатюрные дорожки, которые рассеивают свет. Расчет на то, что поскольку нет пленки, угол обзора и яркость не пострадают.
Я как-то видел 6К-монитор с нанотекстурой в московском ЦУМе. Продавец даже позволил подключить к нему макбук! Но ничего особого я не заметил: обычный матовый экран. За что платить такие деньги?
Я думал, что эксперименты Эпла с текстурой на этом закончатся, но нет. Постепенно ее добавили в другие устройства, например iMac (дополнительной опцией). И вот недавно выкатили в айпадах и макбуках. Устройства с текстурой относятся к категории “кастомных”: их собирают не массово, а на заказ, из-за чего вы не найдете их в розничной продаже. У “кастомок” свои заморочки, о которых я напишу ниже, а пока что вернется к экрану.
Итак, матовый экран — это сказка. Он ничего не отражает, он мягкий, щадит глаза. Светишь на него фонариком — почти все рассеивается. Если сфотографировать экран, вы увидите его содержимое, а не селфи с телефоном. Не заметил, чтобы яркость, угол или рендер шрифтов как-то страдали. Все отлично читается.
Видел картинки шрифтов, сделанные микроскопом с разных экранов. На матовом четкость букв чуть меньше, да, но обычному глазу это незаметно.
Экран с текстурой нежный, легче пачкается. К нему прилагается особая тряпка, и она очень хорошо счищает грязь. Другие тряпки Эпл не одобряет.
Архитектура ARM — это, конечно, полная победа Эпла. После Интела ощущение такое, что спали невидимые гири — настолько все быстро. Ноут больше не закипает при запуске Докера. Программы выскакивают почти мгновенно. Батарея живет ощутимо дольше, раза в два точно.
У меня уже была машина на M1, и даже она после Интела казалась прорывом. А чипы M3-M4 просто творят чудеса. Самое важное: подсознательно чувствуется, что это не ARM в разы быстрее, а Интел что-то делал не так. Иначе откуда такой буст в производительности?
С софтом ситуация не такая радостная. Насколько я понял, всех толковых разрабов забрали в айфон, и десктоп пилят по остаточному принципу. Накопил десятки скринов со всякими нелепостями.
Если вы все еще на Интеле, горячо советую перейти на чипы M1-M4. Это буквально вложить деньги в себя, в свою продуктивность.
Теперь о том, что такое “кастомки”. Есть стандартные конфигурации макбуков, которые массово клепают на заводах Китая и Индии. Именно их вы видите в магазинах. А есть частные конфигурации, доступные на сайте Эпла. Такие модели собирают в США, и это сказывается на доставке: долго и дорого. Кастомки ввозят в соотношении 1 к 10 относительно стандартных конфигураций, потому что на них меньше покупателей. Вероятность того, что у продавца найдется именно та кастомка, которую хочется вам, низкая.
Немного о грустном. Не все так хорошо, кое-где я просчитался, а именно в клавиатуре. Есть два широких стандарта клавиш: европейский и США. У Европы следующие особенности:
- кнопка Enter вертикальная
- обратный слэш слева от него
- тильда и обратный тик слева от левого шифта
У раскладки США все не так:
- Enter горизонтальный
- обратный слэш сверху
- тильда и обратный тик слева от единицы
Много лет я сидел на европейском стандарте: как на самом ноуте, так и на внешней клавиатуре. А поскольку кастомки собирают в США, то положение клавиш у них тоже по стандарту США. И насколько я знаю, на это нельзя повлиять. Заказал кастомку — получи раскладку США. В конфигураторе можно выбрать дополнительный язык клавиш, но это всего лишь гравировка. Макет клавиатуры не поменяется.
Получаются боль и слезы. В сотый раз нажимаю Enter и попадаю в обратный слэш. Жму тильду – а там растянутый шифт. Только сейчас понял, насколько важна тильда: она часто встречается в кложурных макросах. Она нужна в маркдауне, а маркдаун нынче везде: в Телеграме, в Слаке, в Гитхабе и так далее.
Ясно, что когда-нибудь переучусь, но подгорает порой знатно.
Вот что я хотел рассказать вам про маки и Эплы.
-
Bathroom model
Интересное чтиво на выходные. Некие чуваки написали пейпер о новом методе поиска свободных ячеек в хеш-таблице (по-другому называется пробирование). Метод называется Bathroom model и является отсылкой к тому, как ищется пустая кабинка в общественном туалете. Не припомню, когда в последний раз искал кабинку по этой схеме, но спорить не буду. Прилагаются сравнение с тремя другими способами: случайным, по экспоненте и воронкой.
В некоторых случаях Bathroom быстрее конкурентов, но. Код на гитхабе довольно скромный, и хотелось бы больше замеров. На мой взгляд, говорить о прорыве рано, но повозиться интересно. Код и замеры авторов.
UPD: на проверку оказалось ерундой.
-
О еврочиновниках
Я как-то писал о проблеме, что каждый сайт показывает выпадашку с куками. В конце обещал рассказать о еврочиновниках, которые все это устроили. Эта заметка – о них.
В широком смысле еврочиновник не отличается от российского или американского чиновника. Их главная черта – реактивный стиль управления. “Реактивный” означает не “быстрый”, а от слова “реакция”. Сперва чиновник реагирует самым глупым образом, а потом (и если вообще) думает, нужно ли было реагировать.
Пример: если с крыши падает лед, поставим таблички “осторожно, падает лед”. Если кто-то следит за пользователем при помощи кук, поставим плашку “этот сайт использует куки”. В обоих случаях главное – выполнить KPI, отчитаться и пойти дальше. О последствиях чиновник не думает, ему не до таких мелочей.
В результате 99 сайтов из 100 показывают плашки, что сайт исползует куки. Уже одно оформление говорит о полной неразберихе. На одном сайте это полоска внизу экрана, а на другом – модалка во весь экран. Где-то одно предложение, где-то графомания, которая не вмещается по высоте. Кто-то блюрит контент, пока не нажмешь кнопку.
На фоне неразберихи появляются сервисы, которые берут часть проблем на себя. Например, Cookiehub внедряет виджет выбора кук. Их клиентов можно понять: проще платить двадцать евро в месяц, чем попасть по доносу конкурентов на 30 тысяч евро (реальный случай).
Грамотность чиновников, которые принимали закон, сводится к урокам информатики в школе. Учитель заставлял их открыть сайт в Интернет-Эксплорере, найти файлы куки, удалить их и убедиться, что сайт не узнает пользователя. Все мы делали это в школе, и наши европейские сверстники не исключение. Беда в том, что в 40 лет их компьютерная грамотность осталась на том же уровне. Отслеживать пользователя можно сотней способов, но у чиновника в голове одно: куки.
Когда смотришь, во что превратился интернет, разве не очевидно следующее? Если каждый сайт уведомляет о технологии X, это значит, она повсеместна и уведомлять о ней бессмысленно. Бесконечные плашки превращаются в шум, люди закрывают их инстиктивно. Блокировщики рекламы уже включают функцию удаления плашек. На одном конце провода эти плашки продуцируются, на другом – удаляются. Жгутся такты процессора, выделяется тепло. Зачем? Какая цель?
Давайте пойдем дальше: когда клиент садится в такси, уведомим его, что машина работает на бензине, а бензин опасен. Когда человек входит в бизнес-центр, потребудем согласие на то, что в здании используется газ и электричество – тоже опасные вещи. Пользователь предупрежден, свою задачу мы выполнили.
Почему бы не подвергнуть закон пересмотру? Найти чиновников и спросить: что хорошего принесли уведомления о куках? Стало ли меньше трекинга и преступлений? Стал ли интернет безопасней? Было ли хоть раз так, что человек заходит на сайт и такой: опачки, здесь куки, пойду-ка я на другой сайт? Это просто смешно.
Поэтому я считаю, что любой закон должен приниматься только на определенный срок. Годен до, так сказать. Когда срок истек, чиновники собираются и решают – продлить как есть или что-то поменять. Ключевой момент в том, что это будут уже другие чиновники. Кто-то из прежних перейдет в другие отделы, кто-то в бизнес, женщины – в декрет. Придут новые ребята и, возможно, поправят бред, принятый по ошибке десять лет назад. Это даст шанс, что ошибка продлится только несколько лет, а не сотню-другую.
Искренне не понимаю, почему в Европе не нашлось энтузиастов, которые положили бы этому конец? Я имею в виду группу экспертов: программистов, опенсорщиков, членов всяких комитетов. Они бы собрали материалы и факты, организовали бы встречу с чиновниками и популярно объяснили им, что они натворили. Добились бы частичной отмены и точных формулировок. Но ничего подобного не видно: все послушно лепят плашки на сайтах, словно овцы, которых ведут на убой. Всякие Греты Тунберг и другие отбитые личности собирают толпы, когда речь о борьбе с климатом и ковиде. А когда что-то важное, то тишина: это для нашей безопасности.
Верю, что плашки с куками не навсегда. Найдутся те, кто скажут: задолбало, мы этот закон не писали, мы его не уважаем, ставить плашку не будем (я уже нашелся). Этот бред нужно перетерпеть. Не исключено, что дальше будет хуже, но я смотрю в будущее с оптимизмом.
-
Аналоговое образование
Не помню, чтобы кто-нибудь высказывал следующую мысль. Школьное образование должно быть исключительно аналоговым. Никаких электронных учебников, платформ, мессаджеров, онлайн-дневников и прочего. Странно, что это мало кто понимает.
Теперь длинно. Российское айти развивается довольно неплохо, и верный признак этого – компании собирают деньги там, где раньше не могли, а именно в образовательном секторе. Исторически считалось, что школы бедные и с них нечего взять. Однако оплату повесили на родителей, и дело пошло. Напоминает фирмы, которые продают товары детям – аудитории, у которой нет денег – но за них платят родители.
В образовании айтишный элемент является чистым наркотиком. Это бесплатная первая доза, когда платформу внедряют якобы бескорыстно, а потом выясняется, что нужно купить тарифный план. Сайт платформы работает бесплатно только на десктопе. Мобильное приложение показывает только часть данных, а если хочешь все – оформляй подписку.
Любая платформа предполагает, что у ребенка есть телефон, электронная почта и логин. Все эти данные сливаются партнерам в целях рекламы. Я не поленился и прочитал политику обработки ПД одной из платформ: там указаны восемь фирм, включая Яндекс.
Некоторые платформы делают вход через другие. Например, чтобы попасть в Я.Класс, нужно войти через электронный дневник, а вход в него работает через Госуслуги. Представили длину этой цепи? Сто редиректов, попапы, токены… Как это можно объяснить ребенку?
Гаджеты и платформы плохо влияют на учителей, они деградируют в профессиональном плане. Во время ковидной истерии все родители познали дно этой деградации. Ни один учитель не мог достойно организовать удаленное образование. Ни у кого нет материалов для распечатки, контрольных, типовых заданий. Учитель не может составить задание ученикам. Каждое домашнее задание – это ссылка на какую-то говно-платформу, где нужно регистрироваться и подтверждать учетку телефоном, и которая работает только в Хроме на винде.
Учителя и школы оказались голыми. Нет никакой базы знаний: офлайн-лекций, методичек, контрольных работ, которые распечатал и готово. Я как отец трех детей (двое учатся в школе) просто ох…ал с этого, простите. Когда училка опять кидает ссылку на образовательный портал, хотелось лупить ее линейкой со словами: ты учитель или кто? Сядь и составь задание для детей, это же час работы. Тебе же самой пригодится в дальнейшем. Какого хрена ты тащишь детей в очередной стартап?
Я вообще считаю, что учитель без личной базы лекций, заданий и методичек – это не учитель. И на проверку большинство учителей оказались такими.
Мне повезло: я учился у преподавателей, которые готовили матералы сами. Конечно, они опирались на учебник, но изложение было авторское. Исписанный листочек в руках препода – очень хороший признак. В университете прогульщики искупляли грехи тем, что набирали эти листочки и печатали методички, которые позже ходили по рукам.
Айти-компании, которые сегодня захватывают образование, прикрываются благими целями. Разумеется, все это ложь. Компании важна прибыль, а качество образования ее нисколько не интересует. Это слишком долгосрочная цель, за это время или фирмы не останется, или руководство уйдет в другое место. Об образовании должно думать правительство, но у него другие приоритеты. Вся надежда на родителей.
Классика: все онлайн-штучки на проверку оказываются эфемерны. Что-то лагает, тут недоступно, сессия истекла, зайдите через сервис Х, браузер не поддерживается, у вас блокировщик рекламы, введите логин, который ребенок придумал год назад… словом, привычное нам айтишное дерьмо. Я стерплю, не вопрос, но причем тут мои дети?
Образовательные платформы, электронные учебники, дневники, видео-курсы, что там еще… все это замечательно, но не имеет отношения к образованию. Кому-то нравится – ради бога, пользуйтесь, платите. Но школа должна быть в стороне от этого. У ребенка должна быть книга, тетрадь, ручка и учитель – вот все, что нужно для хорошего обучения.
-
Что такое Disruptor?

Графомания бывает не только в русском, но и в английском языке. Хороший пример — страница проекта Disruptor.
Вижу большой заголовок “What is Disruptor?”, но ни один параграф не отвечает на вопрос, что это такое.
Первый параграф о том, что в такой-то фирме борются за перформанс.
Второй параграф о том, что Disruptor — это результат исследований и тестов. Мы тестировали кеши процессора и ядра и сделали дружественный к железу фреймворк.
Третий параграф — это не специализированное решение, подойдет всем.
Четвертый параграф — он работает не так как вы привыкли, может быть непривычно.
Далее ссылки и документация, а еще нас залайкал известный чел.
Внимание, вопрос — что такое Disruptor?
Вижу такое постоянно. Автор пишет заголовок, а дальше Остапа понесло: мы работали, исследовали, у фирмы долгая история, а вот был случай…
Не надо так. Отвечайте на заголовок, который сами же написали.
-
Вырезалки на Маке
У меня тут накладки: вышел из строя личный ноут. Ставить Телеграм и прочие штучки на рабочий ноут я не рискую, поэтому пару дней потратил вот на что: достал с антресолей стренький мак 2014 года. Мой первый мак, в котором, как в греческом корабле, давно заменены все детали. Но я считаю его тем самым маком.
Переустановил ось, накатил софт, и в процессе пришла в голову эта заметка.
На том маке, что сейчас в отключке, я работаю четыре года. Там настроено все: блокировщик рекламы и вырезалка плашек с куками; отключены все нотификации; много правил для фаервола Lulu, чтобы программы не лезли в интернет за обновлениями; Фаерфокс работает с полиси, чтобы не показывать модалки и все остальное.
В один момент я всего этого лишился. Ощущения ужасные.
Начнем с того, что каждая программа после запуска хочет показывать нотификации. Неважно какая, неважно зачем. Даже терминал! Уведомления нельзя отключить всем приложениям сразу и позже настроить исключения. Нужно прокликать “нет” для каждой приложеньки.
Про то, что каждое приложение лезет в сеть за обновлениями и показывает модалку, я писал много раз. Приходиться ставить Lulu и затыкать софт.
У меня в системе английский язык, и если заходишь на русскоязычный сайт, во всех браузерах всплывает модалка с предложением перевести. Нужно везде прокликать отказ.
Сюда же Телеграм: если в системе английский язык, предлагает перевести русские каналы. Если русский, то стоит кому-то скопипастить английскую Википедию, как сразу выпадашка с переводом.
Каждый сайт встречает плашкой о том, что использует куки. Каждый без исключения. На StackExchage и StackOverflow плашки размером с могильные плиты. Они не умещаются по высоте, нужно скроллить.
Кроме кук всплывают: выбор города, подписка на емейл-рассылку, телеграм-канал, вход через гугл-аккаунт. Все это нужно прокликивать или вырезать.
Ну и банальная реклама. Я специально поставил ее на последнее место, потому что реклама уже не вызывает таких проблем: крутится слева баннер, ну и пусть крутится. А выпадашки всех мастей закрывают контент и не дают пользоваться сайтом.
В общем, посмотрел я на современный веб и обалдел. Не представляю, как пользуются им обычные люди без блокировщиков, вырезалки кук и фаервола. Куда ни зайди, на тебя кричат уведомлениями и плашками: сделай то, зайди сюда, обновись, купи премиум, подпишись, установи, оцени товар. И не только веб, но и настольные приложения и даже операционка.
Вырезаю все это по-новой и думаю: что будет через десять лет?
-
Схемы JSON
Официальный сайт json.org удивляет. В масштабе 30% схемы становятся огромны и заливают весь экран. В масштабе 300% правый бар наезжает на основную часть, сжимает ее в мышиный хвост, отчего схемы тоже уменьшаются.

В результате схема в масштабе 30% процентов выглядит крупнее, чем в 300%. Разница, на минуточку, целый порядок. Такой вот забавный факт.

У этих выкрутасов есть объяснения: верстка, плавающие дивы, стили, пятое-десятое. Но можно сказать проще: это фронтенд.
-
Ответ с эмодзи
Важная новость: в Microsoft Outlook появились реакции к емейлам. Работает так: вы написали письмо, отправили, а под ним появляются пальчики, сердечки и прочее. Пошарить скриншот не могу, поверьте на слово.
Интересно, как это работает? Особая апишка в протоколе Outlook? Или пустое письмо с заголовком? Или какой-то особый пейлоад? Или если в письме только эмодзи, оно показывается по-другому?
В любом случае, шлю лучи добра пользователям Аутлука.
-
Корпоративные обновления
Когда работаешь на корпоративном ноуте, постигаешь всю беспощадность обновлений. Ничего нельзя отключить, в фоне работают программы, которые следят за обновлениями. Раз в несколько дней обновится то Хром, то Idea, и начинаются выпадашки: Иван, чтобы защитить себя от угроз, поставь обновление! Откладывать можно фиксированное число раз, и в какой-то момент обновление ставится силой — конечно, перед релизом или звонком. Поэтому со временем я стал накатывать обновления на выходных.
Так вот, в который раз попадаюсь на дурацкое поведение Эпла. Вылазит выпадашка: обновись до Секвойи, тянуть больше нельзя. И кнопочка “Install update”. Я закрываю все программы, все реплы, докеры и остаюсь с выпадашкой наедине. Жму кнопку и вижу: отлично, загружаю обновление, осталось 3 часа. Три часа, Карл! Я мог бы ничего не закрывать и работать чуть ли не полдня, пока качается обновление!
Нажимая “Install update”, я рассчитываю, что оно уже загружено и я в шаге от того, чтобы начать установку. А загрузка даже не начиналась! И качать там не три мегабайта, а 5-7 гигов.
Спрашивается, что мешало скачать обновление в фоне? Если от него нельзя отделаться, так скачай сам, зачем парить мне мозги?
Дизайнер тоже хорош: если кнопка запускает загрузку обновления, ее нужно назвать “Download & Install update”. Я ведь хочу самую малость: чтобы на кнопке было написано то, что она делает на самом деле.
Сюда же относится виджет обновления Эппловских программ. Вылазит окошко поверх всего, и там кнопка “Обновить”. Нажимаешь, оно начинает загрузку, а потом сто раз перехватывает форус. Почему нельзя скачать в фоне? Почему нельзя поставить его в фоне? Зачем тыкать в лицо модалки?
Та же самое с Саблаймом. Поработав минут 20, он начинает показывать модалку с прогрессбаром: загружаю обновление. Тупица, что мешает скачать обновление в фоне? Зачем ты показываешь прогресс-бар? Чтобы пользователь смотрел на него? Других дел у пользователя нет?
В общем, сегодня каждая программа обновляется как не в себя, только нормальные обновления так и не сделали. На ум приходит только одно исключение — Хром, который обновляется полностью незаметно. Все остальное — обычные модалки с прогрес-баром.
-
Taggie
Taggie is an experimental library trying find an answer for a strange question: is it possible to benefit from Clojure tags and readers, and how?
Taggie extends printing methods such that types that could not be read from their representation now can be read. A quick example: if you print an atom, you’ll get a weird string:
(atom 42) #<Atom@7fea5978: 42>Run that string, and REPL won’t understand you:
#<Atom@7fea5978: 42> Syntax error reading source at (REPL:962:5). Unreadable formBut with Taggie, it goes this way:
(atom 42) #atom 42 ;; represented with a tagAnd vice versa:
#atom 42 ;; run it in repl #atom 42 ;; the resultThe value is an atom indeed, you can check it:
(deref #atom 42) 42Tags can be nested. Let’s try some madness:
(def omg #atom #atom #atom #atom #atom #atom 42) (println omg) #atom #atom #atom #atom #atom #atom 42 @@@@@@omg 42But this is not only about atoms! Taggie extends many types, e.g. refs, native Java arrays,
File,URI,URL,Date,java.time.*classes, and something else. See the corresponding section below.Installation and Usage
Add this to your project:
;; lein [com.github.igrishaev/taggie "0.1.0"] ;; deps com.github.igrishaev/taggie {:mvn/version "0.1.0"}Then import the core namespace:
(ns com.acme.server (:require taggie.core))Now type in the repl any of these:
#LocalDate "2025-01-01" #Instant "2025-01-01T23:59:59Z" #File "/path/to/a/file.txt" #URL "https://clojure.org" #bytes [0x00 0xff] #ints [1 2 3] #floats [1 2 3] #ByteBuffer [0 1 2 3 4] ...Each expression gives an instance of a corresponding type: a
LocalDate, anInstane, aFile, etc…#bytes,#intsand similar produce native Java arrays.You can pass tagged values into functions as usual:
(deref #atom 42) 42 (alength #longs [1 2 3]) 3To observe what happends under the hood, prepend your expression with a backtick:
`(alength #longs [1 2 3]) (clojure.core/alength (taggie.readers/__reader-longs-edn [1 2 3]))Internally, all tags expand into an invocation of an EDN reader. Namely,
#longs itemsbecomes(taggie.readers/__reader-longs-edn items), and when evaluated, it returs a native array of longs.EDN Support
Taggie provides functions to read and write EDN with tags. They live in the
taggie.ednnamespace. Use it as follows:(def edn-dump (taggie.edn/write-string #atom {:test 1 :values #longs [1 2 3] :created-at #LocalDate "2025-01-01"})) (println edn-dump) ;; #atom {:test 1, ;; :values #longs [1, 2, 3], ;; :created-at #LocalDate "2025-01-01"}It produces a string with custom tags and data being pretty printed. Let’s read it back:
(taggie.edn/read-string edn-dump) #atom {:test 1, :values #longs [1, 2, 3], :created-at #LocalDate "2025-01-01"}The
writefunction writes EDN into a destination which might be a file path, a file, an output stream, a writer, etc:(taggie.edn/write (clojure.java.io/file "data.edn") {:test (atom (ref (atom :secret)))})The
readfunction reads EDN from any kind of source: a file path, a file, in input stream, a reader, etc. Internally, a source is transformed into thePushbackReaderinstance:(taggie.edn/read (clojure.java.io/file "data.edn")) {:test #atom #ref #atom :secret}Both
readandread-stringaccept standardclojure.edn/readoptions, e.g.:readers,:eof, etc. The:readersmap gets merged with a global map of custom tags.Motivation
Aside from jokes, this library might save your day. I often see people dump data into .edn files, and the data has atoms, regular expressions, exceptions, and other unreadable types:
(spit "data.edn" (with-out-str (clojure.pprint/pprint {:regex #"foobar" :atom (atom 42) :error (ex-info "boom" {:test 1})}))) (println (slurp "data.edn")) {:regex #"foobar", :atom #<Atom@4f7aa8aa: 42>, :error #error { :cause "boom" :data {:test 1} :via [{:type clojure.lang.ExceptionInfo :message "boom" :data {:test 1} :at [user$eval43373$fn__43374 invoke "form-init6283045849674730121.clj" 2248]}] :trace [[user$eval43373$fn__43374 invoke "form-init6283045849674730121.clj" 2248] [user$eval43373 invokeStatic "form-init6283045849674730121.clj" 2244] ;; truncated [clojure.lang.AFn run "AFn.java" 22] [java.lang.Thread run "Thread.java" 833]]}}This dump cannot be read back due to:
- unknown
#"foobar"tag (EDN doesn’t support regex); - broken
#<Atom@4f7aa8aa: 42>expression; - unknown
#errortag.
But with Taggie, the same data produces tagged fields that can be read back.
Supported Types
In alphabetic order:
Type Example java.nio.ByteBuffer#ByteBuffer [0 1 2]java.util.Date#Date "2025-01-06T14:03:23.819Z"java.time.Duration#Duration "PT72H"java.io.File#File "/path/to/file.txt"java.time.Instant#Instant "2025-01-06T14:03:23.819994Z"java.time.LocalDate#LocalDate "2034-01-30"java.time.LocalDateTime#LocalDateTime "2025-01-08T11:08:13.232516"java.time.LocalTime#LocalTime "20:30:56.928424"java.time.MonthDay#MonthDay "--02-07"java.time.OffsetDateTime#OffsetDateTime "2025-02-07T20:31:22.513785+04:00"java.time.OffsetTime#OffsetTime "20:31:39.516036+03:00"java.time.Period#Period "P1Y2M3D"java.net.URI#URI "foobar://test.com/path?foo=1"java.net.URL#URL "https://clojure.org"java.time.Year#Year "2025"java.time.YearMonth#YearMonth "2025-02"java.time.ZoneId#ZoneId "Europe/Paris"java.time.ZoneOffset#ZoneOffset "-08:00"java.time.ZonedDateTime#ZonedDateTime "2025-02-07T20:32:33.309294+01:00[Europe/Paris]"clojure.lang.Atom#atom {:inner 'state}boolean[]#booleans [true false]byte[]#bytes [1 2 3]char[]#chars [\a \b \c]double[]#doubles [1.1 2.2 3.3]Throwable->map#error <result of Throwable->map>(see below)float[]#floats [1.1 2.2 3.3]int[]#ints [1 2 3]long[]#longs [1 2 3]Object[]#objects ["test" :foo 42 #atom false]clojure.lang.Ref#ref {:test true}java.util.regex.Pattern#regex "vesion: \d+"java.sql.Timestamp#sql/Timestamp "2025-01-06T14:03:23.819Z"The
#errortag is a bit special: it returns a value with no parsing. It prevents an error when reading the result of printing of an exception:(println (ex-info "boom" {:test 123})) #error { :cause boom :data {:test 123} :via [{:type clojure.lang.ExceptionInfo :message boom :data {:test 123} :at [taggie.edn$eval9263 invokeStatic form-init2367470449524935680.clj 97]}] :trace [[taggie.edn$eval9263 invokeStatic form-init2367470449524935680.clj 97] [taggie.edn$eval9263 invoke form-init2367470449524935680.clj 97] ;; truncated [java.lang.Thread run Thread.java 833]]}When reading such data from EDN with Taggie, you’ll get a regular map.
Adding Your Types
Imagine you have a custom type and you want Taggie to hande it:
(deftype SomeType [a b c]) (def some-type (new SomeType (atom :test) (LocalDate/parse "2023-01-03") (long-array [1 2 3])))To override the way it gets printed, run the
defprintmacro:(taggie.print/defprint SomeType ^SomeType some-type writer (let [a (.-a some-type) b (.-b some-type) c (.-c some-type)] (.write writer "#SomeType ") (print-method [a b c] writer)))The first argument is a symbol bound to a class. The second is a symbol bound to the instance of this class (in some cases you’ll need a type hint). The third symbol is bound to the
Writerinstance. Inside the macro, you.writecertain values into the writer. Avobe, we write the leading"#SomeType "string, and a vector of fieldsa,bandc. Callingprint-methodguarantees that all nested data will be written with their custom tags.Now if you print
some-typeor dump it into EDN, you’ll get:#SomeType [#atom :test #LocalDate "2023-01-03" #longs [1 2 3]]The opposite step: define readers for
SomeTypeclass:(taggie.readers/defreader SomeType [vect] (let [[a b c] vect] (new SomeType a b c)))It’s quite simple: the vector of fields is already parsed, so you only need to split it and pass fields into the constructor.
The
defreadermutates a global map of EDN readers. When you read an EDN string, theSomeTypewill be held. But it won’t work in REPL: for example, running#SomeType [...]in REPL will throw an error. The thing is, REPL readers cannot be overriden in runtime.But you can declare your own readers: in
srcdirectory, create a file calleddata_readers.cljwith a map:{SomeType some.namespace/__reader-SomeType-clj}Restart the REPL, and now the tag will be available.
As you might have guessed, the
defreadermacro creates two functions:__reader-<tag>-cljfor a REPL reader;__reader-<tag>-ednfor an EDN reader.
Each
-cljreader relies on a corresponding-ednreader internally.Emacs & Cider caveat: I noticed that
M-x cider-ns-refreshcommand ruins loading REPL tags. After this command being run, any attempt to execute something like#LocalDate "..."ends up with an error saying “unbound function”. Thus, if you use Emacs and Cider, avoid this command. - unknown