• Типы в рантайме: глубже в кроличью нору

    Когда я начинал писать заметку «Типы, где их не ждали», мне казалось, что я осилил принести эрланговские типы в рантайм и теперь могу их использовать в клиентском коде на эликсире. Ха-ха, как же я был наивен.


    Все, что предложено по ссылке, будет работать для явных определений типа по месту использования, наподобие use Foo, var: type(). К сожалению, такой подход обречен, если мы хотим определить типы где-нибудь в другом месте: рядом в коде при помощи атрибутов модуля, или, там, в конфиге. Например, для определения структуры мы можем захотеть написать что-то типа такого:


    # @fields [foo: 42]
    # defstruct @fields
    
    @definition var: atom()
    use Foo, @definition

    Lighthouse in French Catalonia


    Код выше не то, что не обработает тип так, как нам хочется — он не соберется вовсе, потому что @definition var: atom() выбросит исключение ** (CompileError) undefined function atom/0.

    Но не все так плохо.
  • Типы, где их не ждали

    Давайте представим себе реализацию модуля Scaffold, который генерирует структуру с предопределенными пользовательскими полями и инжектит ее в вызываемый модуль при помощи use Scaffold. При вызове use Scaffold, fields: foo: [custom_type()], ... — мы хотим реализовать правильный тип в Consumer модуле (common_field в примере ниже определен в Scaffold или еще где-нибудь извне).


    @type t :: %Consumer{
      common_field: [atom()],
      foo: [custom_type()],
      ...
    }

    Было бы круто, если бы мы могли точно сгенерировать тип Consumer.t() для дальнейшего использования и создать соответствующую документацию для пользователей нашего нового модуля.


    Lighthouse in French Catalonia

    Генерация типа структуры без СМС
  • «O tempora, o mores!»

    Для протокола: заголовок я позаимствовал у Цицерона, в Oratio in Catilinam Prima in Senatu Habita.


    Cicero Denounces Catiline, fresco by Cesare Maccari, 1882–1888




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

    Библиотека Tempus
  • Перевозим волка, козу и капусту через реку без эффектов на Elixir

    Становится уже доброй традицией — все любопытное, что появилось на Хаскеле — повторять на Эликсире.


    Первой ласточкой были «Примерно 20 строк для подсчета слов», появившиеся как алаверды на «Побеждая C двадцатью строками Haskell: пишем свой wc» от 0xd34df00d — сегодня же я наткнулся на «Перевозим волка, козу и капусту через реку с эффектами на Haskell» от iokasimov и тоже не устоял.


    Итак, встречайте: ленивый полный асинхронный параллельный перебор против алгебраических эффектов.

    Читать дальше →
  • Vela → умный кеш для time series и не только

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


    Фламинго


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

    Так родилась библиотека Vela, которая хранит кеш состояния для нескольких значений в заданных временных интервалах. Под капотом она на лету отсеивает плохие и устаревшие данные, а также предоставляет доступ к последним N прошедшим валидацию значениям для каждого ключа (пары валют, в нашем случае).

    Вот как это было сделано
  • Джозеф Лесли Армстронг → Цитаты из выступлений

    От переводчика: Джо Армстронг внес величайший вклад в становление Computer Science. Ниже предлагается перевод статьи из вики-цитатника, посвященной Джо.
    Сто цитат Джозефа Лесли Армстронга
  • Telemetría → метрики без напряжения

    12 июля 2018 года увидел свет первый коммит проекта :telemetry. Автор коммита — Аркадий Гил, но README утверждает, что авторское право принадлежит © 2018 Chris McCord and Erlang Solutions, а последний коммит по состоянию на сегодня был сделан Жозе Валимом.


    Big Brother is Watching You


    Библиотека представляется следующим образом:


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

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

    Но недостатков тоже более, чем хватало
  • Cloister → простое управление кластером OTP

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


    Cloister


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


    Передача сообщений между процессами на разных узлах, а также между ссылками и мониторами прозрачна […]
    На практике все немного сложнее.
  • Как мы проводим собеседования в Барселоне

    Я все-таки решил поделиться нашим опытом приема людей на работу, и решил я это сделать по двум причинам: нам удалось собрать всех самых сильных разработчиков нашего стека в городе, и люди, которые приходят — уходят от нас крайне редко (точнее, был лишь один случай ухода в собственный бизнес).


    Все, что написано ниже, может вам подойти, а может — и нет. Я не претендую на истину в последней инстанции, я просто рассказываю, к чему пришли мы, и почему нам это нравится. Также я поделюсь примерами паттернов поведения и кода, которые практически однозначно решают за, или против, кандидата — невзирая почти ни на что остальное.


    Мы — продуктовая компания, нам не нужны вахтовые работники на три месяца. Это тоже накладывает отпечаток на процесс отбора. Мы не в состоянии конкурировать по зарплатам с молодыми заинвестированными стартапами (это не значит, что мы работаем за копейки, просто перекупить талантливый мозг не получится). Зарплата выше средней по рынку, но можно найти галеры сразу тысяч на десять годовых щедрее. Нам приходится искать свой путь завлечения специалистов, и я о нем расскажу.

    Поехали.
  • Примерно 20 строк, примерно такие же результаты: wc на Elixir

      Полгода назад Крис Пеннер опубликовал Beating C With 80 Lines Of Haskell: Wc. В предисловии говорится:


      Задача состоит в том, чтобы построить более шустрый клон оптимизированной вручную реализации утилиты wc на C в нашем любимом высокоуровневом языке программирования со сборкой мусора — на Haskell! Звучит достаточно просто, не так ли?

      Крис прошел весь путь от простой реализации при помощи ByteStrings, через моноиды, встроенные моноиды и, наконец, пришел к параллельной многоядерной версии вышеописанного, которой и удалось немного побить чистый C-код во время выполнения на четырех ядрах.


      Несколько дней назад на Хабре была размещена еще одна заметка на ту же тему от 0xd34df00d Побеждая C двадцатью строками Haskell: пишем свой wc. Автор доказал возможность пользования идиоматического хаскеля и в 20 (двадцати) строках кода реализовал алгоритм, который почти в десять раз быстрее, чем идиоматическая реализация на C.

      Пройдем след в след на Эликсире
    • Не боги горшки обжигают

        На пороге создания нового проекта


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


        Silla Niza

        Внедрение собственной системы мониторинга на примере
        • +14
        • 5,8k
        • 8
      • Хуки времени компиляции в Elixir

          Elixir снабжен сложной, очень хорошо продуманной, инфраструктурой макросов. С легкой руки Криса Маккорда, в сообществе существует негласный закон, который неизбежно озвучивается сразу, как только речь заходит о макросах: «Первое правило использования макросов — вы не должны их использовать». Иногда с малозаметной ремаркой, набранной бледно-серым шрифтом четвертого кегля: «только если вам этого не избежать, и вы очень хорошо понимаете, на что идете, и чем рискуете». Это связано с тем, что макросы имеют доступ ко всему AST модуля, в котором они используются, и, вообще говоря, могут до неузнаваемости изменить получившийся код.


          Я в принципе согласен, что не следует использовать макросы в процессе ознакомления с языком. Пока вы не можете, будучи разбуженным в три часа ночи с похмелья, ответить на вопрос, выполняется ли этот код на стадии компиляции, или же в рантайме. Elixir — компилируемый язык, и в процессе компиляции происходит выполнение кода «верхнего уровня», полное раскрытие синтаксического дерева до тех пор, пока мы не окажемся в ситуации, когда дальше раскрывать уже нечего, и вот этот результат в конечном итоге и компилируется в BEAM. Когда компилятор встречает вызов макроса в исходном коде, он полностью раскрывает AST для него и впихивает вместо собственно вызова. Понять это невозможно, это можно только запомнить.

          Не, попробуем разобраться и понять...
        • Добавляем очень быстрый JSON API к нашему приложению

          Все наши микросервисы, вне зависимости от того, как они общаются друг с другом, предоставляют своего рода heartbeat интерфейсы, чтобы система мониторинга могла в любой момент узнать, как там дела; типа общего состояния здоровья и каких-то специфичных частностей, скажем, контрольных сумм для внутренних данных, с которыми они имеют дело. Речь не про основной транспорт: тут прекрасно справляются RabbitMQ и Redis.


          А еще иногда имеет смысл предоставить простейший (HTTP) интерфейс для экспорта актуальных данных. Думая и в этом направлении тоже, в долгосрочной перспективе я хочу полностью избавиться от Redis в пользу внутреннего решения для хранения пар ключ-значение, как мы успешно сделали ровно два года назад с PubSub.


          Поэтому вместо того, чтобы заново изобретать велосипеды с каждым новым микросервисом, я решил создать подключаемую библиотеку, которая могла бы решать эту бесхитростную проблему по предоставлению произвольных данных из любого приложения с нулевым кодом (если не считать трех строчек в config.exs). Будь то простой heartbeat (HTTP 200 OK), или длинный список актуальных курсов валют.


          Решение основано на этом твите Дэйва Томаса.

          JSON API сервер в весе пера
          • +14
          • 4,1k
          • 2
        • Strong Types, или — все-таки — Strong Hypes?

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


            Все, что написано ниже — не более, чем скромное мнение автора (и так-то не самого умного человека в мире, а вдобавок — и посредственного разработчика). Но это мнение основано на более чем 30-летнем профессиональном опыте и карьере, обеспечивавшей надежные и отказоустойчивые решения для бизнеса на протяжении всего этого срока. Кроме того, я убедительно прошу каждого евангелиста сильной типизации сначала написать парсер markdown, чтобы увидеть своими глазами ситуацию, в которой типы не приносят вообще никакой пользы.

            Слабая аргументация
          • Разработчики — никакая не элита, а голые короли индустрии

            ЛОЛШТО?


            Пожалуйста, не поймите меня неправильно. Я профессиональный разработчик с 30-летним стажем. Я могу читать и понимать почти двадцать языков, полных по Тюрингу. Я могу писать ясный и выразительный код на доброй дюжине из них. В языках, которые я действительно люблю и использую ежедневно — мое имя можно увидеть на доске почета StackOverflow (топ-20 в мире: ruby, elixir). Я по-настоящему люблю писать код, и я отклоняю все предложения «вырасти» по должностной лестнице, будь то руководство проектами, CTO, или что угодно в этом направлении, несмотря на потенциальное увеличение дохода в разы.


            professional beggars were often seen as people not deserving of aid
            — Abraham Willemsens (Metropolitan Museum of Art)


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

            Читать дальше →
          • Эффективная сортировка данных типа Struct

              Все, пришедшие в Elixir / Erlang из других языков, скорее всего, имеют некоторые ожидания относительно того, как должны работать операторы сравнения >, <, == и т. п. Можно было бы ожидать, что 1 < 2, (и это действительно так). В принципе, можно сказать, что сравнение работает как надо. Но не всегда.


              В Elixir / Erlang можно сравнивать все что угодно. Вообще. В то время как для двух операндов одного типа результат не обескураживает, как в приведенном выше примере, сравнение двух операндов разных типов приводит к довольно неожиданным последствиям. Потому что сами по себе типы «упорядочены для сравнения». Вот таким образом:


              number < atom < reference < function < port < pid < tuple < map < list < bitstring

              Что внезапно приводит к тому, что полностью легитимное сравнение 42 < nil возвращает true.

              Версия 1.10 решает эту проблему для структур
            • Мониторинг приложений при помощи Logger.Backends

                Elixir в полной мере использует инфраструктуру ведения журнала Erlang для создания логов. Начиная с версии 1.10, которая должна быть выпущена в ближайшее время, нам становятся доступны новые пользовательские функции ведения журнала, которые появились в Erlang/OTP 21+.


                В то время как OTP предоставляет всю инфраструктуру для доставки журнальных событий (ивентов) абонентам, само протоколирование, если понимать его как хранение и/или отображение событий журнала, должно быть реализовано приложением. С этой целью вводится соответствующая абстракция Logger.Backend.

                Читать дальше →
              • Iteraptor: библиотека для глубокого прозрачного мап-редьюса

                  Структуры данных Elixir — иммутабельны. Это здорово с точки зрения уверенности в том, что наши данные не будут искорежены до неузнаваемости в каком-то другом нерелевантном куске кода, но это немного раздражает, когда нам нужно изменить глубоко вложенную структуру.


                  У нас есть блестящая абстракция Access, которая донельзя упрощает четыре основные операции на глубоко вложенных объектах, при помощи экспортируемых по умолчанию из Kernel функций:


                  В что, если нужен глубокий map-reduce?
                • StackOverflow — больше, чем просто хранилище ответов на глупые вопросы

                    Этот текст задуман и написан как дополнение к «Чему я научился за 10 лет на Stack Overflow».

                    Сразу скажу, что я согласен с Мэттом Бирнером фактически во всем. Но у меня есть несколько дополнений, которые мне кажутся достаточно важными, и которыми я хотел бы поделиться.


                    Я решился написать эту заметку потому, что за семь лет, проведенные на SO, я достаточно хорошо изучил сообщество изнутри. Я ответил на 3516 вопросов, задал 58, вошел в hall of fame (top 20 во всем мире) в обоих языках, на которых пишу постоянно, подружился со многими умными людьми, и активно пользуюсь, пожалуй, всеми возможностями, предоставляемыми сайтом.


                    Каждое утро, за утренним кофе, я открываю ленту новостей, twitter, и — SO. И я считаю, что этот сайт может дать разработчику гораздо больше, чем сниппет для копипаста, заботливо предложенный DuckDuckGo.

                    Неочевидные преимущества активного членства на SO