Category: it

Category was added automatically. Read all entries about "it".

flow

2019 - Компиляторное

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

Фактически, у меня не компилятор "алгоритмов и структур данных", а компилятор произвольных пользовательских требований, где основной проход это requirements gathering. В любой точке исходников, где доступен какой-либо тип, к этому типу могут быть добавлены новые требования, подобно тому как новая бизнес-логика добавляет триггеры в базе данных к существующей старой схеме. Для достижения этого типы и модули должны во время requirement gathering находиться в "многомировой" интерпретации, позволяя ситуации вроде нескольких одноимённых полей в типе, из которых при обращении выбирается нужное для контекста, а не привычный вариант с "заранее выкинуть остальные по ifdef". Если преждевременно создать варианты какого-нибудь типа Entity для нескольких контекстов (натив на сервере, SQL в базе данных, JS на клиенте), то и требования придётся дописывать к каждому из. Кроме того, не все из этих требований будут нужны в выбранном контексте. Например, какие-нибудь хинты по memory layout не являются условными, но применимы только в нативе. Теперь с этим хорошо.

Далее я сделал паузу, чтобы разобраться с другой темой. Синтез конфигураций, упомянутый в https://justy-tylor.livejournal.com/255577.html

Сначала я написал алгоритм с применением необычной many-valued логики, который плющит конфигурации. Затем подобрал удобный способ объявлять правила в мейнстримных языках программирования, не требующий интеграции логических движков. Для правил с простыми фильтрами и множествами - способы редактировать в UI и хранить в базе данных. И даже подход к решению Frame problem. В общем, увлёкся, благо легко и весело.

Но дальше оказалось хитрее. Окей, вот конфигурации в типах, типы наследуются, конфигурации в них плющатся, всё в порядке, ручного описания приоритетов конфигураций не требуется. Однако, программа или модуль при этом получается конфигурацией конфигураций. Даже тип это конфигурация конфигураций в тех случаях, когда язык содержит мощные инструменты кастомизации (как redeclare или constrainedby в Modelica). Есть ли для такой ситуации взаимодействия нескольких иерархий единый правильный способ вывода последовательности для "плющить", покрывающий все интересующие меня кейсы (сразу или с минимальной дополнительной разметкой)? Или потребуется модификация самого алгоритма? Или почти всё автоматически, но иногда с ручными приоритетами? Нарисовал кучу возможных решений, далее предстоит оценить и выбрать что-то работающее. Что, помимо прочего, хорошо повлияет на систему типов и систему модулей в языке.

С такими мыслями сейчас завершаю "компиляторный" 2019. А "танцевальный" и прочие пока продолжаются.
flow

Забавное


A Talk Near the Future of Python

Содержание: опытный джедай на виду у юных падаванов пишет простейшую VM на Python. Потом лёгким движением руки превращает эту VM в полнофункциональную VM для WebAssembly, которая запускает геймкод скомпилированный из Rust, используя pygame вместо вызовов JS/canvas.

Хорошего пятничного просмотра.
flow

Исследования-дыбр

После некоторого перерыва (включавшего как летние танцы/приключения, так и дела) продолжаю с компилятором. Не секрет (уже мелькало в чатах), что разработка прототипа ведётся на C#. Лет 5 назад я бы сам удивился такому решению, но сейчас .NET это прямо из коробки открытая и кроссплатформенная экосистема, дающая желаемую скорость итераций в exploratory programming.

Параллельно всплыла ещё одна тема - динамический синтез единой конфигурации из разрозненных (и местами противоречивых) требований. Управление правами доступа (к сущностям в базе данных или файлам на диске), описание правил сборки ПО, интеграция каких-либо сервисов или приложений в операционную систему, интеграция плагинов в расширяемый программный продукт - всё это работа с фрагментами требований, авторы которых не могут предсказать содержимого фрагментов из других источников на целевой системе, намерений, с которыми они созданы, а также всего множества ситуаций, возникающих при взаимодействии двух и более фрагментов. Похоже, что мне удалось подобрать представление фактов и алгоритм вывода, работающий с такими фрагментами независимо от предметной области, и дающий интуитивно понятные (а также идеально воспроизводимые на тех же исходных данных) результаты интеграции конфигураций. Ещё в 2011 году, когда мы работали над .15926, vvagr задал мне вопрос, можно ли логикой (а не вставкой extension points и кода на Python) описывать расширения и кастомизацию UI продукта. Я ответил "наверное да, но настоящего решения пока нет, и его поиск может занять очень долгое время" (добавление интерпретатора Prolog или miniKanren создало бы лишь "иллюзию логики", не решая проблему фрагментарных описаний). А сейчас решение есть. Но на 8 лет позже. И хоть и может быть применено в компиляторе (про который в абзаце выше) в какой-то момент, но к разработке ядра компилятора отношения не имеет. В общем, хорошо что случилось, чуть жаль, что только "сейчас", а не "тогда".

Также, продолжил старую тему идентификации криптохэшами, начатую в https://justy-tylor.livejournal.com/252597.html Как по части 4D-идентификации ролей, так и по части идентификации данных для content-addressable storage. Но это заслуживает отдельного поста.
flow

Когда требуется больше времени

В 2013 году я "завершил" интеграционную часть своего исследования в области языков программирования и моделирования. 8 месяцев (при 6 планировавшихся) переосмысления и интеграции знаний, которые десятилетиями накапливались человечеством и годами собирались мной, когда-то как хобби, а затем и целенаправленно. Цель была: вывести набор решений для создания языка программирования следующего поколения и перейти к созданию прототипа.

Предпосылки к успешности данной затеи:
1. Более 30 лет появления новых знаний со времён тех идей, на которых базируется сегодняшнее поколение, а также более полная доступность (благодаря интернету) архивных материалов.
2. Моё желание воспользоваться всем этим опытом прошлого. Как, опять же, показывает история: создатели языков чаще концентрируются на создании "better X with Y", игнорируя большую часть опыта за пределами своей привычной ниши, чем и обуславливается "топтание на месте", а местами и деградация в этой области. Видеть целое это возможность цельно решать существующие проблемы, а не создавать локальные нишевые заплатки.

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

И тогда, в 2013, когда необходимая информация была выведена, я приступил к созданию прототипа компилятора. Началось бодро. Но что-то пошло не так. Я обнаружил, что пишу очередной гибридный язык, как Scala, Nemerle или сегодняшние Kotlin и Swift, но с уклоном в расширяемость. И что пишу очередной "компромисный" компилятор, где прибитые гвоздями фичи выглядят логично с точки зрения основного языка, но снижают потенциал развития. В то же время, накопленные за годы знания продолжали работать, приводя к удобным новым решениям, которые прекрасно подходили в виде EDSL-библиотечки на "допишу позже", но противоречили сложившимся дизайнам и коду прототипа уже сейчас.

Так проявилась моя ошибка. Недостаточно просто создать платформу, обеспечивающую бесшовные переходы между воплощениями "успешных идей прошлого" в виде EDSL. Интеграция старых идей порождает новые, лучше. Так разработка приостанавливается. Пишется следующий прототип, но в процессе требования опять меняются. Становится ясно, что разработка преждевременна.

С тех пор прошло 6 лет, из которых многие сотни часов были затрачены на новое исследование. Не совмещение старых успешных подходов в одном языке, а синтез новых, заменяющих как старые, так и "белые пятна" между ними. Более того, полученные таким образом дизайны также сменялись множество раз. Как и дизайн компилятора, который поначалу никак не дотягивал до желаемой системы обработки независимых правил.

Прошлым летом дизайны ещё раз изменились кардинально, но с тех пор скорее дополнялись. Модель компиляции в части совмещения независимых правил и решения противоречий OWA и CWA (open world assumption и closed world assumption) выглядит оптимально. Время действовать.

На этой неделе я начал работать над прототипом нового компилятора. С обновлёнными силами и навыками.

Планировалость одно исследование на 6 месяцев. Получилось другое на 6 лет. 6M6Y. В чём-то как 3D2Y в One Piece.
Luffy_Pays_His_Respects.png
flow

Немного эволюции в визуальщине

И так, шёл 2018 год, и после пары десятилетий рассмотрения различных визуальных средств (наряду с прочими языками программирования и моделирования), я с удивлением наткнулся на решение, которое на голову выше _любых_ визуальных языков, созданных в метафоре "соединить порты".

Antimony CAD. Это практически неизвестный широкой публике хобби-продукт под Linux/macOs, но в сети можно найти пару демонстрационных видео:
https://vimeo.com/125111378
https://www.youtube.com/watch?v=uigjofZ_3HM

И так, ключевые преимущества:
1. Входные и выходные порты в одной колонке.
2. Входные порты также являются и выходными, в большинстве случаев.

Пункт [1] просто улучшает читаемость. Что же даёт [2]? При использовании визуальных средств "с портами", как правило, ваши намерения и спецификации могут быть воплощены лишь с потерями. Вы не можете заявить "Node1.N = что-то" и "Node2.N = Node1.N". Вам придётся вводить сторонние общие ноды с "ёжиками" связей. И это не только ухудшает читаемость схемы, но и отдаляет имплементацию от спецификации. В Antimony же эта проблема решена.

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

Comment to 'Инженеры, хватит бегать от ответственности' by tonsky

Мне кажется, что корректно идентифицируя проблему ты ошибаешься при идентификации причин. Программисты не стали менее мотивированы. Халтурщики - да, напрягаются меньше, потому что "формочки" с ошибками в девяностые падали громко, а повебень на JS тихо и незаметно для пользователя (до какого-то момента), но это тоже не является определяющим фактором.

Прикладное ПО - "лимонный" рынок по Акерлофу. Планку качества на таком рынке повышают акторы с нерыночной мотивацией. Однако, более сложные производственные цепочки (а они содержат и такие внешние артефакты как веб-браузеры, например) нивелируют вклад мотивации индивида. А именно разрастание производственных цепочек в разработке ПО мы и наблюдали в минувшие десятилетия.

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

View the entire thread this comment is a part of

flow

Основы понимания дизайна языков

За последние 20 лет я исследовал сотни языков программирования и описания данных. Включая не только хоть как-то известные, что применяются сейчас или доступны в исторических материалах, но и множество DSL, которые (обычно без какой-либо документации) встречались в софте, играх или продуктах демосцены.

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

Но сейчас, в недавних разговорах, я всё же подобрал хороший рецепт. Последовательность такая:
1. Изучить материалы HOPL ( https://en.wikipedia.org/wiki/History_of_Programming_Languages ).
2. Исследовать языки из свежего Top 20 TIOBE ( https://www.tiobe.com/tiobe-index/ ). Update: Коллега в чатике верно подметил, что картину сегодняшнего дня лучше отражают данные Stack Overflow, так что вместо TIOBE можно брать их ( https://insights.stackoverflow.com/survey/2017#technology ).

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

В этом смысле показательны материалы HOPL. Если при прочтении у вас возникнет ощущение "сложно, но интересно" - продолжайте. Если же это будет ощущение отторжения - ок, стоп, значит не ваша тема. Вообще, или на данном этапе жизни.

Если что: можно не разбираться в языках программирования, не понимать их как явление, но при этом быть успешным "программистом на знакомых языках и готовых фреймворках". Это не плохо и не хорошо. Разные ситуации требуют разных навыков и интересов.
flow

Идентификация 4D-документов через криптохэши

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

Предыстория.

Вышел тогда летом у vitus_wagner пост с отсылкой к старой теме чеширнета (децентрализованная соцсеть), а у меня тогда мысли витали в близких направлениях (пересылка произвольных документов между личными и корпоративными системами менеджмента данных, с автоматическим встраиванием на корректную позицию, проверками целостности, etc), так что в поисках вдохновения я решил перечитать уже порядком подзабытое из https://vitus-wagner.livejournal.com/tag/cheshirenet

В чеширнете также предполагались некие типы документов и возможность публикации обновлённых версий существующих документов. Но меня смутил предлагаемый способ идентификации самих документов - на основе псевдослучайных UUID (GUID) из RFC 4122. Ещё обдумать не успел, а подсознание уже указывает: "грабли здесь, грабли".

Ведь можно взять любую отдельно взятую систему (или несколько), и заменить там сообщение с важной новостью от Пети на собщение с котофоточками от Васи, без какого-либо изменения UUID. А дальше - выяснение "что же там было на самом деле", поиск консенсуса, и прочие действия, которых можно избежать. И вот как.

Идентификация 4D-сущностей через криптохэши.

Для начала уточним терминологию. Статичный (неизменяемый) документ или отдельно взятое состояние изменяемого документа легко идентифицируются криптохэшем от данных (и иногда - от дополняющих их метаданных). Это используется во множестве современных технологий: системы контроля версий, документориентированные СУБД, magnet-ссылки и прочее. Такие неизменяемые документы или состояния/версии документов это 3D-документы, они не зависят от времени.

В свою очередь, есть 4D-документы, редактируемые. Их содержимое может быть изменено или заменено в разные моменты времени (причём, разным образом в разных возможных мирах, но не будем сейчас углубляться в эту тему). 4D - потому что появляется время как измерение (более подробно про 4D можно прочитать в BORO или ISO 15926). Соответственно 4D-документ имеет свою отдельную идентификацию, а его содержимое представлено множеством 3D-документов (версий), в зависимости от времени и других условий.

Например, обыденными идентификаторами для 4D-документов являются пути в файловое системе и HTTP/HTTPS-ссылки. Но для них необходима централизация для обеспечения уникальности, в первом случае осуществляемая операционной системой, а во втором процедурами DNS. Или альтернатива - те самые псевдослучайные UUID (GUID).

Но есть и другой способ. Если первая версия 4D-документа создаётся именно как версия (для чего достаточно, например, наличия даты и криптографической подписи), то сам 4D-документ можно идентифицировать под криптохэшу первой версии.

Пример: вы написали новую статью и запускаете её в сеть (с датой и подписью). SHA-256 от 3D-документа первой версии будет "NNN...". Затем вы обнаружили несколько опечаток и публикуете вторую версию статьи. В метаданные этой и всех следующих версий также добавляется запись "document_id:sha256:NNN...". Дата, подпись.

Чем это лучше использования псевдослучайных значений? Если идентификация 4D-документа делается по криптохэшу первой версии, то можно проверить:
1. Что некий предлагаемый 3D-документ является первой версией обсуждаемого (так как совпадёт криптохэш).
2. Что некая предлагаемая новая версия документа содержит ту же подпись, что и первая версия документа - для этого достаточно одновременно предоставить первую версию, с нужным криптохэшем.

Чуть отвлечённо.

Вообще, имеет смысл и гибридная идентификация документов, 4D и 3D одновременно. Ситуация: автор написал статью, затем обновил, вы оставили комментарий об оставшихся неточностях, автор обновил ещё раз, и теперь ваш комментарий не соответствует содержимому статьи и выглядит странно. Этого можно избежать, если документ с комментарием содержит как идентификацию 4D-документа статьи, так и идентификацию 3D-документа той версии, на которую вы отвечали: "in_reply_to(document_id:sha256:NNN1..., version_id:sha256:NNN3...)".

В общем, используйте. Возможно вам пригодится. Возможно мне пригодится.
flow

Ещё про Evernote

( Продолжая http://justy-tylor.livejournal.com/251595.html )

В общем, во вторник я сконвертировал своим скриптом все заметки. Циклы статей с веба - в единые .html с картинками, собственные записи - в .txt по категориям. Перенести из .enx в .enex было бы даже проще, но при таком уровне поддержки продукта (если они сами не могут потратить несколько часов на конвертер) - ну нафиг. Пока решаю, попробую для интеграции заметок Scrivener, а там как пойдёт.
flow

Об универсальных языках программирования/моделирования 2

По мотивам предыдущего поста меня спросили в личке, типа чем так плох XML и ручные конфиги на нём. Раскрываю тему.

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

2. Проблемы ручных конфигов. Если в конфигурации встречаются описания настраиваемых однотипных объектов, то, как правило, многие фрагменты описаний повторяются или взаимозависимы. Большинство информационных систем не позволяет работать с фрагментами, вынуждая пользователя копипастить описания множество раз, со всеми сопутствующими рисками ошибок. Однако, даже в тех системам, которые позволяют использовать в конфигурации группы или именованные пресеты, обычно отсутствуют более тонкие механизмы настройки, константы, вычислимые выражения. А если следовать за развитием требований, то единственным решением становится полноценный язык программирования (для интереса - посмотрите историю языка Lua). Лучше сразу переходить к этому, чем городить недовелосипеды.

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

Именно поэтому универсальный язык должен поддерживать в качестве таргетов произвольные форматы и представления, а не только "код".