• The Pact library for Clojure

    (This is a copy of the readme file from the repository.)

    Pact is a small library for chaining values through forms. It’s like a promise but much simpler.



    [com.github.igrishaev/pact "0.1.0"]


    {com.github.igrishaev/pact {:mvn/version "0.1.0"}}

    How it works

    The library declares two universe handlers: then and error. When you apply them to the “good” values, you propagate further. Applying the error for them does nothing. And vice versa: then for the “bad” values does nothing, but calling error on “bad” values gives you a chance to recover the pipeline.

    By default, there is only one “bad” value which is an instance of Throwable. Other types are considered positive ones. The library carries extensions for such async data types as CompletableFuture, Manifold and core.async. You only need to require their modules so they extend the IPact protocol.


    Import then and error macros, then chain a value with the standard -> threading macro. Both then and error accept a binding vector and an arbitrary body.

    (ns foobar
       [pact.core :refer [then error]]))
    (-> 42
        (then [x]
          (-> x int str))
        (then [x]
          (str x "/hello")))

    If any exception pops up, the sequence of then handlers gets interrupted, and the error handler gets into play:

    (-> 1
        (then [x]
          (/ x 0))
        (then [x]
          (str x "/hello")) ;; won't be executed
        (error [e]
          (ex-message e)))
    "Divide by zero"

    The error handler gives you a chance to recover from the exception. If you return a non-exceptional data in error, the execution will proceed from the next then handler:

    (-> 1
        (then [x]
          (/ x 0))
        (error [e]
          (ex-message e))
        (then [message]
          (log/info message)))
    ;; nil

    The -> macro can be nested. This is useful to capture the context for a possible exception:

    (-> 1
        (then [x]
          (+ x 1))
        (then [x]
          (-> x
              (then [x]
                (/ x 0))
              (error [e]
                (println "The x was" x)
    ;; The x was 2
    ;; nil

    Besides then and error macros, the library provides the then-fn and error-fn functions. They are useful when you have a ready function that processes the value:

    (ns foobar
       [pact.core :refer [then-fn error-fn]]))
    (-> 1
        (then-fn inc)
        (then-fn str))
    ;; "2"
    (-> 1
        (then [x]
          (/ x 0))
        (error-fn ex-message))
    ;; "Divide by zero"

    Chaining with then and error is especially good for maps as allowing destructuring:

    (-> {:db {...} :cassandra {...}}
        ;; Get a user from the database and attach it to the scope.
        (then [{:as scope :keys [db]}]
          (let [user (jdbc/get-by-id db :users 42)]
            (assoc scope :user user)))
        ;; Having a user, get their last items from Cassandra cluster
        ;; and attach them to the scope.
        (then [{:as scope :keys [cassandra user]}]
          (let [items (get-user-items cassandra user)]
            (assoc scope :items items)))
        ;; Do something more...
        (then [...]

    Fast fail

    To interrupt the chain of then handlers, either throw an exception or use the failure function which is just a shortcut for raising a exception. The function takes a map or a message with a map:

    (ns foobar
       [pact.core :refer [then error failure]]))
    (-> 1
        (then [x]
          (if (not= x 42)
            (failure "It was not 42!" {:x x})
            (+ 1 x)))
        (error-fn ex-data))
    ;; {:x 1 :ex/type :pact.core/failure}

    Supported types

    The core namespace declares the then and error handlers for the Object, Throwable, and java.util.concurrent.Future types. The Future values get dereferenced when passing to then.

    The following modules extend the IPact protocol for asynchronous types.

    Completable Future

    The module pact.comp-future handles the CompletableFuture class available since Java 11. The module also provides its own future macro to build an instance of CompletableFuture:

    (-> (future/future 1)
        (then [x]
          (inc x))
        (then [x]
          (/ 0 0))
        (error [e]
          (ex-message e))
    "Divide by zero"

    Pay attention: if you fed an instance of CompletableFuture to the threading macro, the result will always be of this type. Thus, there is a deref call at the end.

    Infernally, the then handler calls for the .thenApply method if a future and the error handler boils down to .exceptionally.


    The pact.manifold module makes the handlers work with the amazing Manifold library and its types. The Pact library doesn’t have Manifold dependency: you’ve got to add it on your own.

    [manifold "0.1.9-alpha3"]
    (-> (d/future 1)
        (then [x]
          (/ x 0))
        (error [e]
          (ex-message e))
    "Divide by zero"

    Under the hood, then and error handlers call the d/chain and d/catch macros respectively.

    Once you’ve put an instance of Manifold deferred, the result will always be a Deferred.


    To make the library work with core.async channels, import the pact.core-async module:

    (ns foobar
       [pact.core :refer [then error]]
       [clojure.core.async :as a]))

    Like Manifold, the core.async dependency should be added by you as well:

    [org.clojure/core.async "1.5.648"]

    Now you can chain channels through the then and error actions. Internally, each handler takes exactly one value from a source channel and returns a new channel with the result. For then, exceptions traverse the channels being untouched. And instead, the error handler ignores ordinary values and affects only exceptions. Quick demo:

    (let [in (a/chan)
          out (-> in
                  (then [x]
                    (/ x 0))
                  (error [e]
                    (ex-message e))
                  (then [message]
                    (str "<<< " message " >>>")))]
      (a/put! in 1)
      (a/<!! out) )
    ;; "<<< class java.lang.String cannot be cast ..."


    To run the tests, do lein test or just make test.

    © 2022 Ivan Grishaev

  • Стоп-слова

    Перечислю слова, которые никогда не использую и не советую вам. С объяснением почему.

    Токсичный. Это слово по праву считается словом 2021 года. Внезапно всё у всех стало токсичным: коллеги, начальство, рекрутеры, близкие, родственники. Бездумно выдернутое из английского языка, слово перешло в русский без какого-либо смысла или конкретики.

    Когда я слышу о токсичном человеке, мне не хватает деталей. Ну, токсичный, а что это значит? Чаще всего под этим имеют в виду “неприятный”, но все равно — чем именно неприятен человек? Он матерится? Делает замечания по работе? Не по работе? Он курит и затем дышит табаком на коллег (токсичен в буквальном смысле)?

    Короче, мне нужны детали — что именно делает человек, как он себя ведет, что говорит. На практике оказывается, что его токсичность — плод воображения рассказчика, который с кем-то не ужился. Поэтому без конкретики слово “токсичный” ничего не значит.

    Скам. От этого слова у меня просто горит. Бездумно вырванное из английского, в русском оно совершенно чужеродно. Скамом назывыют все то, в чем не разбираются, но считают подозрительным: криптовалюту, проекты Илона Маска. Нормальным считается заголовок в духе “Почему X это скам”. Хочется разбить автору лицо.

    У английского слова scam есть точный, однозначный перевод — мошенничество. Других синонимов нет, точка. Вопрос — на кой черт притягивать слово, у которого есть четкий перевод? Я еще пойму английское privacy, которое трудно уместить в одно слово. Но для scam в этом нет смысла — обман, мошенничество.

    Скамом называют все то, что им не является. Если учесть, что скам — мошенничество, то называя что-то скамом, вы должны понимать, в чем оно состоит. Ради интереса я спрашивал у некоторых людей, почему они называют скамом криптовалюту. Ответ удивил своей убогостью: потому что криптой платят за оружие и наркотики. Ох, беда.

    Когда кто-то платит за оружие криптой, это не скам — обе стороны отдают и получают именно то, что ожидали, поэтому мошенничества нет. А когда вам звонит сотрудник безопасности Сбербанка и предлагает перевести деньги на “защищенную” карту — это мошенничество. Это значит, одно лишь участие криптовалюты не делает операцию с ней скамом, и операции с рублями не означают, что все чисто.

    Короче, осторожней со “скамом” — слово короткое, а объяснить, что за ним стоит, трудно. Считаю дурным тоном использовать слова, смысл которых не понимаешь.

    Лайфхак. Пошлое, уныле слово, которое заменило бездну русских слов. Способ, метод, прием, подход, решение, рецепт, алгоритм, подсказка, находка, идея — продолжать можно до бесконечности. Где-то в сети я видел картинку: перечислены эти слова, и подпись: если всё это у вас “Лайфхак”, то вы долбоёб. Грубовато, но в целом верно. Совершенно не вижу смысла в “лайфхаке”, когда говорю о способе решить проблему.

    Ивент, риквест. Аналогично скаму, у этих слов есть точный, однозначный перевод. Event — событие, мероприятие, request — заявка, обращение. Поэтому когда вижу текст вроде “проведем корпоративный ивент”, становится стыдно от чужой тупизны. Самое дно — писать эти слова через и, то есть ивент и риквест. Получается декартово произведение тупизны и стыда.

    Сторителлинг. Глупость этого слова обеспечена тем, что оно состоит из двух английский слов: story (история) и tell (сказать кому-то). В русском языке есть более емкое “рассказ”, когда человек доносит мысль или историю до слушателей. Как устно, так и письменно.

    Таким образом, сторителлинг становится рассказом. Сторителлер, прости господи, это рассказчик. Курсы сторителлинга — курсы навыка рассказа, уроки рассказывания, мастерство рассказчика.

    Современный сторителлинг, как правило, это гнилая реклама. К ней добавляют нелепых персонажей и дурацкий сюжет в надежде, что прокатит. Другой тип сторителлинга — доклады со сцены, когда человек рассказывает очевидные истины, прохаживаясь по сцене взад-вперед, смотря в пол и делая глубокие паузы.

    Бумеры, зумеры. Не припомню случая, чтобы понадобилось выделить часть аудитории по возрасту. Подобная выборка отдает расизмом — предвзятостью к людям по определенному признаку. Фраза “зумеры не поймут” или “бумеры проходят мимо” в принципе не могут звучать вежливо и подходят только для пререканий в сети. Ответ “окей, бумер” я считаю настолько тупым, что кроме вздоха у меня нет другой реакции.

    Выгорание. Никакого выгорания нет, есть доведенная до крайности усталость. То “выгорание”, которым страдает половина интернета, лечится сном, отказом от гаджетов в вечернее время, планированием дел на бумаге, разговорами с коллегами, начальством, родными. Всё, вы здоровы.

    Уверен, читатели подскажут другие вредные слова, которых лучше не говорить.

  • Не словом, а делом

    Как правило все сервисы, когда мы в них логинимся, присылают письмо. Там написано когда и с какого устройства был выполнен вход. Подобные письма присылают банки, мессаджеры, социальные сети, крипто-биржи. Это хорошо и правильно.

    Как-то раз я внимательно прочитал подобное письмо. Смутила фраза, которую можно перевести так:

    Если это вы, все в порядке. Если нет, немедленно заблокируйте ваш аккаунт.

    Давайте представим, что вас взломали. Вы ничего не делали, тупили в телефон, и вдруг пришло письмо, что из Украины зашли ваш клиент-банк или биржу. Все, паника. Время идет на секунды. У мошенников все отработано, они моментально переводят деньги.

    Что делать? Писать в техподдержку на support@foobar.lol? Уже сам факт того, что это support, говорит о том, что они доберутся до моего тикета в лучшем случае через час. Звонить? Номера нет под рукой, надо найти и потом висеть в очереди, слушая дурацкую музыку. Можно заблокировать личный кабинет через личный кабинет, но чтобы это сделать, надо сперва попасть в личный кабинет, верно? А мошенники могут этому помешать, например сменив пароль.

    Оказавшись в подобной ситуации, вы поймете: фраза “немедленно заблокируйте ваш аккаунт” — чистой воды профанация. Это можно сделать, только заранее потренировавшись. А кто будет тренироваться, да к тому же еще на разных сервисах?

    Должно быть так. Вместо фразы “немедленно заблокируйте ваш аккаунт” в письме должна быть жирная красная кнопка “ЭТО НЕ Я!!! ЗАБЛОКИРОВАТЬ АККАУНТ!!!”. Ссылка подписана токеном, который действует пять-десять минут. Даже если письмо со временем утечет, ссылкой нельзя будет воспользоваться.

    Ссылка перебрасывает на форму, где нужно подтвердить блокировку. Форма отправляется методом POST, чтобы всякие preview-сервисы не стриггерили блокировку за вас. После отправки формы аккаунт замораживается, все активные сессии завершаются, транзакции в очереди отменяются. Далее восстанавливаем доступ через поддержку.

    Такая схема — истинная забота о клиенте. Не просто “заблокируйте аккаунт”, а все необходимое на месте. Конечно, она тяжелее в реализации, но сохранит деньги клиента и репутацию фирмы.

  • Качество Excel

    Каждый раз, когда запускаю Эксель, поражаюсь, насколько он ужасен. Годы идут, столько всего меняется в лучшую сторону, а офисный пакет Микрософта так и остается дном.

    Например, прислали мне CSV-файлик. Эксель уверен, что умеет его открывать, потому что при установке связал с собой расширение .csv. Тыкаю. Открывается картина:

    Ну еб жеж тебя! Не умеешь открывать – зачем полез?

    По пунктам:

    1. Все поля слиплись в одну строку. CSV это Comma Separated Values, так? Comma значит запятая. Но придурочный Эксель делит поля по точке запятой. Comma, любезнейший, вы понимаете английский? Почему нельзя добавить простой детектор — пробежать строку и проверить, каких разделителей больше? Не понимаю.

    2. Вместо русских букв — даже не кракозабры, которые случаются, если читать utf-8 как cp1251, а какие-то греческие письмена. Омеги, сигмы. Что происходит? Опять же, нельзя что ли прочитать десять строк и сделать анализ кодировки?

    3. Ссыкливая надпись Possible Data Loss в первой желтой полоске. Некоторые данные могут быть потеряны. Что бы мне об этом пишешь, идиотский эксель? Сразу открой в формате Экселя, чтобы я мог пользоваться всеми возможностями. И только потом, если захочу, экспортирую проект в csv. А храниться он будет в Эксель-файле. Короче, разработчики не понимают разницу между проектом и промежуточным форматом. Беда.

    4. Еще одна ссылкивая полоска с информацией о том, что нужно обновиться. Ни за что не поверю, что эти проблемы исправили в последней версии, так что зачем?

    Другие мелочи. В нормальных программах, если мы редактируем элемент, нажимаем ввод. В экселе для редактировании ячейки надо нажать F2. Почему не F9 или F12? Тоже хорошие клавиши, и в них столько же логики.

    Нажатие Enter перемещает курсор на ячейку вправо. Почему? Если я хочу вправо, то нажму стрелочку. Почему ввод что-то перемещает?

    А вот тот же документ в Google Sheets. Кодировка нормальная, все разбилось по ячейкам, вопросов нет:

    К чему это все?

    Отдельные персонажи поругивают веб-приложения, что не натив, а декстоп весь такой шустрый, нативный, си-плюс-плюс. В широком плане это неправда — бывает так, а бывает наоборот.

    Браузерный JS уже давно быстрый как незнамо что. Сравните работу в Adobe Illustrator (плюсовую настольную программу) и Фигму (Js, React + Canvas). И все станет ясно.

    Или настольный Эксель с гугловым Sheets.

    Десктопный софт может нещадно тормозить, а браузерный — плясать на кончиках пальцев. Десктопный софт может застрять в прошлом на два десятка лет, потому что там же застряли его разработчики.

    Так что нет одного пути, все условно и не ложится на обобщения.

  • Опыт с телевизором

    Сегодня не модно любить бренды вроде Эпл и Икеи, которые якобы заботятся о пользователях. Уже не новость, что за мнимую заботу потребитель дорого платит и подсаживается на иглу бренда. Однако у других фирм с заботой вообще все плохо.

    Первое января 2022 года. Имеем дорогущий телевизор LG с OLED-матрицей. Это не просто хороший телевизор, а в принципе лучший вариант, что предлагает рынок. Своего рода Макбук-Про M2, если судить в таких категориях.

    Так вот, казалось бы. Даже при столь высокой цене ни упаковать, ни подготовить к распаковке в LG его не смогли. Видимо, нет отдела, который занимается тем же в Эпле. Плюс ворох мелких косяков.

    Например: достаю телевизор из коробки, собираюсь повесить на кронштейн. Выясняется, что в комплекте нет болтов для VESA-крепления. Дырки есть, а четырех болтов стоимостью, сука, 50 копеек каждый — нет.

    Ладно, открываю пакетик с крепежом для кронштейна. Вижу два набора болтов: большие и маленькие. А на телевизоре дырки под СРЕДНИЕ. Получается чемодан без ручки. Дорогой, топовый чемодан. Но без ручки.

    В тот момент я подумал, что неплохо бы вернуть смертную казнь, причем трансграничную. В Корею или Китай вылетает наш истребитель, захватывает служащих LG, от рабочего до исполнительного директора, и везут в Воронеж. Там показательно четвертуют на площади с трансляцией в интернет. Чтобы запомнили: если есть резьба, то в комплект должен быть болт под нее.

    Отрываюсь от мечтаний. Первое января, магазины закрыты, купить болты не получится. Спокойно, товарищи: поставим телек на подставку и подождем до послезавтра. Беру подставку. При перемещении слышу, как брякает кусок металла. Елозит внутри, словно мыло в раковине. Уроды из LG не закрепили его, просто стыд.

    После сборки подставка шатается. Поначалу мозг отказывается это принимать: подставка, предназначенная держать экран стоимостью около ста тысяч рублей, шатается. Кот пробежит, хвостиком махнет, и плакал твой телевизор. Ну или дети.

    Эта гифка стоит тысячи слов и океана эмоций:

    Вращается как шайба на льду. Это еще пол кривой, а на ровной поверхности крутится как спиннер.

    В общем, обшарил я все полки-коробки и нашел пару нужных болтов. Еще пару скрутил здесь и там. Шайбы из комплекта оказались слишком толстыми, заменил на свои. Весь этот колхоз удачно лег друг на друга, как парад планет, и телек я повесил. С удовольствием повесил бы еще пару корейцев, которые отвечают за комплектацию.

    Поймите меня — я не просто ною. Так делать нельзя, просто нельзя. Когда товар дорогой, забота о покупателе не просто желательна, она обязательна. В комплекте должно быть буквально все, что только понадобится: болты, гайки, стяжки, крепления, клипсы и остальное. Еще шестигранники и одноразовые отвертки. Все это стоит гроши — я ведь не прошу из закаленной инструментальной стали.

    Та же Икея кладет в набор все перечисленное. Собираешь шкаф — вот тебе шестигранник, гаечный ключ и отвертка. Купил четыре кресла — получишь четыре пачки отверток и прочего. До сих пор по тумбочкам лежат.

    Еще лучше пример — Эпл. Одно время я интересовался их 6К-монитором стоимостью в полмиллиона. Не чтобы купить, конечно (он мне не нужен), а с точки зрения товара. Как он выглядит, как упакован, как подключается?

    Я был поражен процессом его распаковки. Ощущение, что сидела команда и рассчитывала все варианты: что покупатель подумает, что ему покажется и прочее. Распаковка напоминает запуск космической ракеты. Все уложено именно в таком порядке, и разрезы сделаны в тех местах, и материалы подобраны так, что отклонений быть не может.


    Учтено, что сначала ты ставишь не до конца распакованный экран на подставку и только потом снимаешь остатки упаковки, чтобы не заляпать экран. При этом нет никаких инструкций. На каждом этапе доступен строго один следующий шаг, который как-то выделен. Пользователя не держат за идиота, а помогают ему.

    Ясное дело, кто-то проделал большую работу, и она повышает стоимость товара. Это правильно: человек, который покупает монитор за полмиллиона, вряд ли думает о выживании, его волнует комфорт. Легче заплатить условные тридцать тысяч вместо того, чтобы одуплять сборку самому. Сборка — это досадная процедура, которая отделяет от пользования товаром. Поэтому умные люди стремятся ее сократить.

    Да что там, я бы спокойно купил телевизор и за сто пять тысяч рублей, лишь бы в нем был весь нужный крепеж. Заплатил бы по тысяче за болт, только бы все было на месте. Да, такой я лошок-лопушок: не хочу бегать за болтами в строительный магазин. Подставку бы еще починить — долить миллиметр пластмассы. Не разорились бы.

    Кстати, забавно вспоминать, сколько было шуток про подставку для эпловского монитора. Нога за тысячу долларов! Какой идиот ее купит? Вспоминаю анекдот про Тарантино:

    — Квентин, вы так и не сняли фильма лучше “Криминального чтива”!

    — А кто снял?

    Смех смехом, а лучше той подставки ничего нет. Я ее видел, держал, шатал. Уверяю, когда будут бомбить Воронеж, подставка устоит. Она держит монитор и при этом красива. Видимо, сочетание этих двух и делает ее столь дорогой.

    Если посмотреть на другие мониторы и телевизоры, станет ясно: их подставки либо не держат, либо уродливы. Нет, правда, все подставки отвратительны: какие-то лапы птеродактиля. На работе у меня монитор на 144 герц, который два года назад стоил 87 тысяч. На подставку нельзя смотреть без стыда. Дома монитор на 120 герц, тоже не дешевый. Подставка рвотная. Про телевизор я уже рассказал — у топовой модели она шатается.

    Особое изумление вызывают инструкции к дорогим товарам. Мудаки-производители печатают брошюры объемом на сотни страниц. Плюс всякие купоны, реклама, гарантийные талоны. В итоге набегает на томик Чехова. Но почему-то схему сборки надо обязательно уместить на один лист. Чтобы картинки были со спичечный коробок. Чтобы подносить лист к глазам. Напечатать крупно на трех, четырех листах почему-то нельзя. Бумагу экономят?

    Смотрите, в LG считают, что это понятная инструкция:

    Забавный факт: инструкция предупреждает, что экран хрупкий и при установке его легко продавить пальцем. Как же, мудачье вы этакое, мне его держать? Почему бы не надеть на края тонкие пенопластовые бамперы, которые стоят вообще нисколько? Может, вместо предупреждений лучше обезопасить покупателя?

    Короче, выводы.

    • Даже покупая дорогой товар, будьте готовы, что не хватит винтиков за два рубля. Почему это считается нормой — загадка.

    • Свою продукцию нормально пакуют только Эпл и Икея. Эти фирмы не сахар и порой вытирают ноги о покупателей. Но после их упаковки иметь дело с чем-то другим невозможно.

    • Если вы что-то производите, кладите в комплект все, что может понадобиться. Если покупатель побежал в магазин за чем-то недостающим — фирма обосралась.

    • Сложный товар нуждается в продумывании процесса распаковки и установки. Это повышает цену, но отбивается обзорами и опытом покупателя. Люди готовы платить дороже за комфорт и заботу.

    • Инструкции — крупнее. Нет, еще крупнее. ЕЩЕ СУКА КРУПНЕЕ. Один рисунок — одна страница.

    • Руководствами на малайском, болгарском и т.д. пусть подтирается СЕО.

    • Пригласите случайного Васю с улицы распаковать и включить ваш продукт. Уверяю, узнаете много нового.

    Все, выговорился. Отпустило. Полегчало.

    С наступившим!

  • Ютуб в настольном приложении

    Открывая очередной видос на Ютубе, подумал — так жить нельзя. Мне ведь нужно только видео, а Ютуб в довесок льет рекламу, трекинг, похожее видео, комментарии. Браузер Brave и сторонние блокировщики помогают, но все тормозит. Плюс Гугл постоянно меняет что-то в интерфейсе, и чувствуешь себя животным, чью миску с едой передвинули в другой угол.

    Наверняка же есть настольная прога, которой даешь урл — и она показывает. Слегка погуглил, и выяснилось, что так и есть.

    Знаменитый плеер VLC умеет играть ютубные урлы. И не только ютубные, но и Вимео, BBC и другие (Порнохаба, увы, нет). Реализовано это скриптом на Lua, который по урлу вычисляет прямую ссылку на гугловый стрим.

    Однако выяснилось, что то ли скрипт поломали, то ли Гугл обновился, и теперь просмотр Ютуба не работает. Вот что надо сделать, чтобы его починить.

    Скачайте скрипт youtube.lua с Гитхаба по этой ссылке. Далее зайдите в папку


    На винде и линуксе, понятно, путь будет другим. Удалите файл youtube.luac — это скомпилированный модуль, который сейчас не работает. Скопируйте сюда youtube.lua, что вы скачали. Перезапустите плеер.

    Чтобы открыть ютубный видос в VLC, пройдите по пунктам FileOpen Network или нажмите Command+N. В окошке введите урл.

    Плеер немного потупит, и появится видео:

    Что радует:

    • нет рекламы и трекинга;
    • нет тормозных скриптов;
    • нет оверлеев, по клику на которые улетаешь невесть куда;
    • нет комментариев, рекомендуемых видосов и прочего.

    Такой просмотр анонимный: он не осядет в истории, не будет преследовать годами на главной. Если видео длинное, плеер можно запаузить и свернуть как обычное окно. Не будет лишней вкладке в Хроме.

    Работает перемотка стрелочками, при этом вы сами настраиваете, на сколько секунд. Аналогично с ускорением видео: в выпадающем меню Playback открывается бегунок.

    С качеством видео все сложно. Его можно менять, но настройка спрятана так глубоко, что дойдет только сильнейший. Сначал VLCPreferencesInput / Codecs, кнопка Show All.

    Затем прокрутить до Preferred video resolution. По умолчанию там Best available, что слишком жирно. 1080 или 720 хватит за глаза.


    Чтобы быстро открыть видос, напишем функцию на bash. Добавьте в ваш ~./bashrc или ~./zshrc следующее:

    function play(){
        /Applications/VLC.app/Contents/MacOS/VLC -v $1 &

    Амперсанд на конце запустит процесс в фоне, чтобы можно было закрыть терминал, не прибив плеер. Теперь достаточно вызвать в консоли

    play https://www.youtube.com/watch?v=88UDgKLL7bE

    — и появится плеер с видосом:

    Минус — VLC не сохраняет прогресс просмотра. На длинных видосах, которые смотришь урывками по нескольку дней, можно случайно потерять прогресс.

    Схема не работает с плейлистами: при попытке его открыть запускается только первый видос. Однако VLC поддерживает свои плейлисты. С его точки зрения ютубное видео — один из элементов плейлиста. Откройте по очереди несколько видосов и сохраните в файл m3u. Получается локальный плейлист, не привязанный к учетке гугла. Положите его в Дропбокс или где вы храните файлы.

    Можно вести несколько плейлистов: избранное, посмотреть позже, музыка и так далее.

    В итоге получается полностью анонимный просмотр Ютуба, без рекламы и с поддержкой плейлистов. Пока что я тестирую такой подход, и в целом ощущения приятные — как будто глоток свежего воздуха. Конечно, ощущения другие: здесь программа реагирует медленнее, а здесь быстрее. Неизвестно, к чему приду, но попробовать стоит.

    Если вы знаете аналоги, расскажите в комментах.

  • Advent of Code

    Наступил декабрь, и программисты всего мира бросились решать Advent of code. Кто не знает, это цикл задач на алгоритмы. Каждый день появляется новая задача, а их сложность постепенно нарастает. Задачи обсуждают в интернете, сравнивают решения, спорят… словом, этакий сериал для программистов.

    Пару лет назад я тоже брался за AoC. Мне хватило часа, чтобы понять — никогда не буду этим заниматься, и вот почему.

    Во-первых, формулировка заданий. Когда я читаю про гномов, эльфов и магические камни, то хочется кричать. Неужели нельзя подобрать нормальные термины? У меня уходит сорок минут на то, чтобы понять, что от меня хотят. Мне грех жаловаться на английский, но порой я копирую задачу в гугло-переводчик, чтобы разгрести эту ахинею. Не хочу тратить столько времени на работу — сделать текст понятным, — которую должен был сделать автор.

    Далее, предположим, у вас и вправду зачесались руки что-то покодить. Неужели нет ничего под рукой? Написать библиотеку, какой-нибудь плагин, документацию? Это гораздо полезней, потому что послужит людям. А какая польза в решении задачи с волшебными камнями? Это одноразовый код, страшный и понятный только автору. Он пойдет на помойку.

    Хуже всего тот шум, что производит Advent of Code каждый декабрь. Напоминает бегунов в парке или веганов: они не могут бегать и веганить молча, нужно всем об этом рассказать. Блоги, твиттеры и другие площадки наводняются унылыми постами на тему “AoС day 5 in Rust”. Для меня это красный флаг: если вижу, что автор будет тридцать дней кормить меня “интересными задачками”, отписываюсь без раздумий.

    Advent of Code — это турнир, в котором вам никогда не выиграть. Как правило, все одиннадцать месяцев мы делаем рутину: читаем базу, Кафку и перекладываем данные туда-сюда. Дай бог раз в квартал обходим дерево. Но ни с того ни с сего в двенадцатый месяц надеемся преуспеть в решении нетривиальных задач. С какой стати? Это как новичку пойти в спортзал и каждый день заниматься по два часа. Чем это кончится? Организм не вынесет внезапной нагрузки, плюс добавьте духовное поражение. Так почему вы уверены, что быстренько решите этот бред с гномами и эльфами?

    Advent of Code построил специфическую тусовку. Ее завсегдатаи решают подобные задачи за три минуты. Вступить с ними в соревнование — гарантировано обречь себя на проигрыш. Это чужая среда, чужая повестка, и обычному, заурядному программисту (как мне, например) там делать нечего.

    Сказанное выше не значит, что я против Advent of Code. Ради бога, решайте, если вам нравится. Важно понимать: AoC не сделает вас лучше, если вы им занимаетесь. Ровно так же вы не станете хуже, если вам наплевать. Вы можете быть отличным программистом даже без репозитория advent_of_code_2021 на Гитхабе. А новогодний шум легко и перетерпеть.

  • FAANG не предлагать

    Не понимаю, почему люди так стремятся FAANG. В последнее время пена пошла через край: каждую неделю появляются статьи на тему “Как за полгода я устроился в условный Фейсбук/Гугл”, и конца этому не видно. Истерия достигла такого масштаба, что появились фирмы-нахлебники, которые за скромную сумму готовят к FAANG-у: переписывают резюме, разбирают задачки.

    Я бы не стал писать этот пост, если бы не видел похожие мысли у окружающих. Всем нужен Фаанг; взрослые люди на полном серьезе зубрят по ночам красно-черные деревья, обход графов и прочую муть, которая понадобится им раз в жизни.

    Для меня это своего рода унижение. С какой стати я должен готовиться к собеседованию? Вот он я, что умею, то умею. Расскажу то, что делаю регулярно. Если не знаю, как обойти граф, то быстро нагуглю. В чем проблема-то? Представьте, что программист условного Гугла забыл обход графа. Его что, сразу увольняют? Нет, он как и мы открывает Гугл и находит то, что нужно.

    Но поскольку очередь в гуглы-фейсбуки расписана на пару лет вперед, фирмы позволяют любое измывательство над соискателем. Не развернул связный список – гуляй, нам не нужны неудачники. Постепенно эта модель приходит в Россию. Условные яндексы-тиньковы переняли ту же дрочь на алгоритмы, которую должен выдержать новичок, как в худших традициях студенческих братств.

    Одержимость алгоритмами на собеседованиях переходит все границы. Как ни почитаешь статью какого-нибудь бедняги, которого пять часов мурыжили алгоритмами, так становится не по себе от этой лжи и лицемерия. Алё там: сложные алгоритмы нужны лишь изредка, а основное время программист проводит за рутиной: читает данные из файлов и сети и перекладывает в другое место.

    Зацикленность на алгоритмах говорит о том, что в фирме не понимают, как нанимать людей. Неважно, умеет ли соискатель обходить дерево. Важно, умеет ли он доводить задачу до конца, задавать вопросы, писать письма, общаться с руководством и начальством. Графы и деревья настолько незначительны по сравнению с этими навыками, что просто смешно говорить. Поищите людей, которые обещали к пятнице и сделали к пятнице. То есть не написали код, не открыли pull request, а выкатили, сто раз проверили, и в пятницу фича в бою. Найдёте в лучшем случае пару из ста.

    Фаанги — это инфантильная мечта, которой надо переболеть, вроде как сняться в порно или создать социальную сеть. Или как молодежная группа и толкинизм. В какой-то момент надо повзрослеть и взяться за что-то полезное.

    Удивляюсь, что кто-то питает романтические надежды в адрес этих огромных фирм. Все они давно прошли фазы стартапов и стали машинами по заколачиванию денег. Фейсбук отвратителен до тошноты: от одного вида хочется закрыть браузер. Сотрудникам, которые пилят его каждый день, я бы доплачивал за вредность. Гугл хорош только как поисковик, у других сервисов адский интерфейс. Обе фирмы живут за счет рекламы, которую показывают на базе собранных данных. Собранных самым лживым и обманным способом, с нарушением всех соглашений и норм.

    Загонять себя в FAANG — все равно что добровольно надевать кандалы. Первые несколько лет нужно рвать зад ради репутации. Затем будет трудно уйти, потому что высокая зарплата действует как наркотик.

    Интересно, что все, кого я спрашивал, идут в FAANG ради денег. Так и отвечают: там много платят, x2 по рынку. Это самый пошлый и банальный ответ, и мне даже стыдно его слышать. Но почему — расскажу отдельно, потому что это уже новая мысль.

  • Meet Soothe: a small Clojure library for better Spec error messages

    Note: this post is an adjusted copy of the Readme file from the GitHub repo.

    Soothe provides better error messages for Clojure.spec. It’s extremely simple and robust.

    API Documentation


    • Leiningen/Boot
    [com.github.igrishaev/soothe "0.1.0"]
    • clojure CLI/deps.edn
    com.github.igrishaev/soothe {:mvn/version "0.1.0"}


    Clojure.spec is a piece of art yet misses some bits when dealing with error messages. The standard s/explain-data gives a raw machinery output that bearly can be shown to the end-user. This library is going to fix this.

    The idea of Soothe is extremely simple. The library keeps its private registry of spec/pred => message pairs. The key is either a keyword referencing a spec or a fully-qualified symbol meaning a predicate. The value of this map is either a plain string or a function that takes the problem map of the raw explain spec data.

    Read more →

  • Не смешивать языки

    Пришел к выводу из заголовка: не следует смешивать языки. Не должно быть такого, что эта часть на одном языке, а та на другой. Бек на Питоне, фронт на JS — отстой. Бек на Кложе, CLI на Golang — отстой. Сервис логики на Джаве, сервис авторизации на Расте — отстой.

    Этот языковой цирк усложняет и без того сложную реальность. Раньше я думал, что протоколы и схемы решают проблемы. Не все ли равно, что на том конце провода, если данные в JSON? Оказалось, не все равно.

    Даже если данные в JSON, некоторые языки не могут работать с ними так, как это делают другие. Например, Гоферы и прочие ребята со статической типизацией не могут просто распарсить JSON. Они объявляют три экрана вложенных структур и натягивают на них JSON. Малейшее расхождение, какое-то поле nil — и все упало. Опять созвон и новая задача.

    Когда читал исходники проекта на Golang, который забирает JSON от Кложи, сто раз удивился, зачем добровольно садиться на кактус. Совершенно разные языки и идиомы, подход к коллекциям и обработке данных. На ровном месте впендюрили проблему: случись беда, я не смогу поправить у гоферов, а они у меня.

    Два и более языков — это постоянное переключение контекста. Это свои погремушки: пакетные менеджеры, зависимости, подводные камни. Это разные идиомы. Это неполное погружение в каждую область. Это удел “фулстек-разработчика” — посредственности, который одинаково плохо знает обе среды.

    Стоит ли говорить, что с одним языком проще управлять командами? Удобней перекидывать людей, наполнять общую базу знаний. Вести библиотеки с контрибом.

    На стыке языков всегда будут трения. Вечно будут задачи в духе “этот словарь мы не распарсим, наши убер-классы не позволят, переделай”.

    Команда не может Кложу? Научите их. Несколько дней мастер-классов. Подсадной человек, который поведет за собой начинающих. Заготовка проекта, который будут дорабатывать. Учиться не так уж сложно, если знать как обучать, и в перспективе выгодней.

    Всячески сокращайте языковое многообразие.

Страница 2 из 57