Pull to refresh
231
0
Всеволод @torkve

Пользователь

Send message
Вы говорите об очень маленьких частных задачах. Ну кому, правда, нужно в диффе переименование функции? Как часто это встречается? Люди на ревью же не переименования функций читают? Такие маленькие частные случаи можно сделать чуть ли тривиальным постпроцессингом обычного дифф-файла, без какого-либо анализа AST — и это будет гораздо более простое решение.
А что касается невозможности сохранить: основной смысл моего высказывания был не в точности сохранения какой-то аналоговой информации. В конце концов, если речь идёт, например, о классической звукозаписи, то как правило звук и обложка ­— это вся полезная информация, которую мы можем извлечь с той или иной точностью, потому что в отличие от средневековья, хитрых полустёртых миниатюр и рисунков неопознанными красителями процесс производства пластинок доподлинно известен и под печатью рисунка на диске никогда не скрывается другой рисунок.

Я же говорил о другом: применительно к аналоговой неструктурированной книжке мы просто можем не знать, какую информацию нам надо извлечь, чтобы не потерять полезный сигнал. То есть дело не в количестве, а в качестве.

Точно так же, как в вышеупомянутых адресах мы балансируем между тем, чтобы создать сверхсложную структуру, в которую будем пытаться сложить любые данные и тем, чтобы потерять какую-нибудь возможно (не)важную информацию. Это как сверхуниверсальные стандарты типа SOAP или 7-уровневой модели OSI — настолько универсально, что даже неудобно и люди предпочитают использовать более простые и менее универсальные вещи.
Ну вот тот же пример из статьи с инклюдами: декларативный пример вам правда кажется более понятным?
Или вот, например, декларативные языки популярных систем сборки: Makefile, CMake. Каких только извращений не приходится придумывать людям, чтобы заставить их вести себя как надо. Причём в Makefile всё ещё относительно по-божески: декларативно описывается только граф целей, а сами цели пишутся в императивном стиле. Это позволяет в сложных местах плюнуть на кэширование каких-нибудь промежуточных звеньев, например, и написать просто явную последовательность команд. А в CMake декларативно по умолчанию вообще всё, и сборка сложного проекта выглядит… достаточно адово. В каком-нибудь qbs с его структурированным декларативным описанием из-за этого некоторые вещи в принципе нельзя сделать by design, хотя казалось бы, система сборки должна позволять собирать что угодно и как угодно.
Если domain постоянно меняется, то это уже не domain, а непонятно что. В таких случаях надо либо редизайнить систему, чтобы разобраться, какой же у вас всё-таки domain, либо действительно признать, что его нет и вам нужен язык общего назначения.
Вообще C — это тоже прекрасный пример очень упрощённого языка, так уж. Никаких запутанных фич, всё понятно и предсказуемо.
Но я согласен, пример получился не самый удачный. В любом случае есть ещё SQL, конфиги и куча других мест, где успешно применяется DSL.
Вообще автор существенно перегибает палку. Прямо начиная с баз данных. Неструктурированные данные всегда первичны, и зачастую содержат больше информации, чем структурированные. Потому что заранее неизвестно, какие сигналы из них могут потребоваться, не всегда структура, покрывающая все возможные случаи, удобна.

Например, почтовые адреса: чтобы не рассказывать своими словами, дам ссылку на публикацию об удивительных адресах нашей страны. Можно декомпозировать адрес, предусмотреть сто уровней вложенности, предусмотреть, что для некоторых адресов «город» может превращаться в «городской округ», а внутри него может быть квартал, а в квартале — ещё один город. А потом изобретать способы собрать из этого строковое представление и ловить баги. Проще просто хранить готовое представление. Или хранить его для сложных случаев, а в простых использовать простую схему типа той, что в КЛАДР.

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

Например, код: автор пишет про классный diff, который надо использовать вместо этих ваших строк. Настолько классный, что я даже на секунду задумался, а может правда, написать такой diff, не для питона, конечно, но для языка, где действительно можно построить AST. Потом, конечно, меня отпустило. Вот простой случай переименования автор описал, классный случай. А если взять чуть более сложный случай, был у нас метод из трёх строк: объявили переменную X, вызвали функцию A, вернули результат. Мы тело этого метода переписали в виде четырёх строк: объявили переменную Y, в цикле вызвали функцию B, вернули результат. Представьте себе этот дифф в виде модификаций AST. Удобно ли это читать? А ведь это простая структурированная информация, готовая к потреблению. Можно собирать дифф в виде AST, в простых случаях писать «function renamed», а в сложных опять генерировать текстовый дифф, обязательно скажет мне кто-нибудь. А зачем? Это тройная работа, невообразимое усложнение, только ради диффа? В рефакторинге это полезно, для диффа — нет. Не нужно усложнять алгоритм там, где хорошо работают простые средства. Простые решения работают надёжнее сложных.

Или вот ещё про код: долгие десятки лет большая часть веба была написана на Perl. На языке известном своей парадигмой TIMTOWTDI. Невообразимо усложнённый язык, про который даже доказывали, что его невозможно распарсить. А ведь в моём детстве, когда почти все динамические сайты содержали в себе путь /cgi-bin/, я был уверен, что CGI == Perl. Почему так получилось? Потому что код писался простой, никто не выдумывал адских и сложных решений. Когда вы пишете простой и очевидный инструмент, вам важнее написать его быстро и просто. И прочитать его должно быть просто. Когда «менее мощный» язык зарезает ваши возможности, код становится очевиднее и предсказуемее для машины, но не всегда — для человека. В этом был секрет популярности Perl и PHP, на них было просто разрабатываться, и основным потребителем был человек, а отнюдь не машина. Сейчас, когда задачи, которые решают программисты, в том числе и в вебе, усложнились, сдвинулся баланс: нам надо рефакторить сложный запутанный код, анализировать большие модули с кучей зависимостей и связей, мы перекладываем эту задачу на машину. И вот уже машине удобнее упрощённый язык. Фактически, вместо того чтобы писать для людей, мы теперь пишем для машин. И именно для этого приходится переходить на «менее мощные» языки, придумывать декларативные парсеры MANIFEST.in вместо императивных. Человеку удобнее и понятнее последовательность: «включили одно, потом выкинули другое», а более сложное декларативное описание удобнее только машине.

Поэтому надо формализовать и упрощать всё там, где это нам действительно надо, ad-hoc. А пока потребности нет, оставьте язык для людей, в конце концов им ещё код писать.
В этом месте соглашусь с автором статьи — в общем-то он предлагает то, что называется DSL. Делается язык под задачу и в нём будет сложнее накосячить, а разбирать и обрабатывать его, наоборот, проще. Примеров уже и так полно, языки для описания звуковых эффектов, языки для графики типа GLSL и т.п.
Это-то всё ладно, в таких случаях можно действительно один раз завести пачку сертификатов или заводить для каждого поддомена по мере необходимости, через апи.
Есть более сложные случае, когда есть, например, CNAME с *.domain.ru на domain.ru и никаких фиксированных поддоменов вообще нет. Например, ныне почивший сервис jpg.to использовал имена поддоменов в качестве поискового запроса (хотите найти котика, идёте на котик.jpg.to), тогда новый сертификат можно генерировать только в момент обработки запроса, что безумно.
Я не хочу врать, но возможно, что в акке это вообще настраивается выставленными политиками — так же, как и разнообразные политики доставки, что делать при падении актора и т.п.
В пони этого всего я не вижу.
Нет, смотрите: наш актор бывает в двух состояниях. Изначально он в состоянии successfulPing, в котором он умеет обрабатывать сообщения Ping и Pong, отвечая на них корректным результатом. Все остальные сообщения приводят к ошибке (и, кажется, то ли просто игнорируются аккой, то ли приводят к падению актора, не помню). При этом пинги кроме ответа переводят актор во второе состояние — failPing, в котором мы умеем отвечать на пинг промахом и переходить в первое состояние, а на все остальные сообщения отвечаем отправителю «печалька».
То есть, поведением актора управляет не какая-то сохранённая переменная, а просто выбранная функция-обработчик, которая умеет обрабатывать какие-то типы. Если бы я придумал какую-то более сложную логику, я бы мог написать в этих двух функциях вообще непересекающийся набор типов сообщений, которые они обрабатывают. Таким образом в акке легко можно сделать конечный автомат, который будет переходить между состояниями, и не надо будет писать какую-то сложную логику, которая будет проверять состояние перед обработкой всех возможных типов сообщений. Состоянием будет являться сама функция-обработчик актора, которой достаточно будет знать только доступные именно ей переходы.
class MyFlappingPingPongActor extends Actor {
    case class Ping()
    case class Pong()
    case class Miss()
    case class Failure(msg: String)

    def successfulPing: Receive = {
       case Ping => {
           sender ! Pong()
           context become failPing
       }
       case Pong => {
            sender ! Ping()
       }
    }

    def failPing: Receive = {
        case Ping => {
            sender ! Miss()
            context become successfulPing
        }
        case _ => {
            sender ! Failure("I'm sad, no actions until I'm happy again!")
        }
    }

    def receive = sucsessfulPing
}

Как-то так. Я уже плохо помню скалу, писал по памяти.
Библиотека акторов Akka для скалы, например, предлагает возможность актору изменять в процессе работы своё состояние, изменяя набор обрабатываемых сообщений (состояния при этом ещё можно складывать/доставать из стека), таким образом удобно писать логику работы и реализовывать конечные автоматы.
Из описания совершенно не видно этой фичи в Pony. Там предлагается всё это делать через известно что?
Почему? Ведь HTTP-статус — это «транспортная» часть, статус доступа. А Вы хотите отдавать логическую часть приложения, смешать два уровня.
Не хочется Вас огорчать и расстраивать, но в языке Яист чего-то «своего» придумали чуть более, чем нисколько.
Если чего-то никогда не встречали, никогда не стесняйтесь поискать в интернете.
Логика подсказывает, что у строителей, например, должна быть Изба знакомств. У банкиров — банк кандидатов.
Писать в тексте «ложить» ещё до ката — это очень, очень плохая идея :)
Это на самом деле очень правильно, потому что в оригинальном коде, например, есть очень много кастов между u8/u32/i32, которые легко в определённых ситуациях могут выдать нам мусор, и единственное, что спасает — это допущение, что мы не будем рендерить картинки такого большого размера.
Так что мои допущения с unwrap(), по большому счёту, такие же: я предполагаю, что мы будем инициализировать точки исключительно типами, которые можно свободно конвертировать в/из float, т.е. все те же стандартные численные типы с теми же условиями переполнения.
т.к. раст не позволяет автоматически конвертировать числовые типы

Раст позволяет это делать немного по-другому, но из-за бага в компиляторе, я до недавнего времени, пока не обошёл это, висел в первой части. Сегодня только закоммитил доделанные операции с числами, вот тут можно посмотреть: github.com/torkve/habropengl/blob/master/src/vec.rs

В смысле, конвертировать конечно придётся, но всё в одном месте.
Поправьте имя: Мачей Чижевский.

Information

Rating
Does not participate
Location
Москва, Москва и Московская обл., Россия
Registered
Activity