Category: it

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

|, me, hikki, ok

Хайлайт

Тхис жж ис врыттен ин тхе хопе тхат ит вилл бе усефул,
бут ВИТХОУТ АНЫ ВАРРАНТЫ; витхоут евен тхе имплиед варранты оф
МЕРЧАНТАБИЛИТЫ ор ФИТНЕСС ФОР А ПАРТИЦУЛАР ПУРПОСЕ.
РЫД АТ ЁОУР ОВН РЫСК!
Я предупредил.

Все упоминаемые в данном жж действующие лица вымышленны и не имеют связи с реальными людьми или событиями.

Все мои тексты и рисунки в этом жж, если в самом посте явно не оговорено иное, распространяются по лицензии Creative Commons License
Однако, рисунки из постов с тегом idraw, если в самом посте явно не оговорено иное, распространяются по лицензии Creative Commons License.

Содержательная часть этого жж примерно на три четверти состоит из моих явных и неявных излияний на тему «X — это говно», где X — это почти всё, что угодно, начиная от зубной щётки и POSIX-совместимых API, и заканчивая современной системой высшего образования и интерпретацией археологами архитектуры какой-нибудь древней пирамиды.
Ещё иногда вдруг начинаю писать про [конструктивную] математику (про Haskell там, зависимые типы и всё такое), но в результате всегда получаются серии постов об ужасах жизни, пьяницах-наркоманах-гопниках и войнах с бюрократией.
В объедках иногда встречаются излияния на тему японского визуального искусства, заметки об использовании UNIX-подобных операционных систем и всякий случайный мусор, приходящий мне в голову.

Пишу редко, но если пишу — то много. О уровне моего Чувства Собственного Достоинства можно не сообщать, я прекрасно осведомлён.

Ещё немного бесполезного текста есть в био.

А вообще это — пост для связи, где комменты скринятся.
|, me, hikki, ok

Почти три месяца event_mask is 110111, not able to describe 4th event

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

Из того, что произошло за это время ярко выделяются:
* защита магистерской диссертации,
* поступление в аспирантуру,
* написание отчёта по государственному контракту в TeXе,
* катание по Европе поездами и последствия,
* любовь к NixOS;
* начало ведения другого блога.

Про поступление особенно рассказывать нечего. Поступать в аспирантуру куда-нибудь за бугор просто, чтобы уехать, мне как-то совершенно не хотелось. Числюсь аспирантом в ИТМО, со всеми вытекающими последствиями и очередной сдачей экзамена по философии весной. Правда на этот раз я знаю, о чём там рассказывают на лекциях и спрашивают на экзамене, значительно заранее (вследствие большого количества философских разговоров с неким аспирантом, что старше меня на два года). Кроме того, по этим темам я обстоятельно самостоятельно укрепился в современных нерусскоязычных адвансментах. Поэтому я уверен, что на этот раз ещё до начала я знаю больше экзаменаторов по этим столь важным вопросам (при условии, что они читают только переведённую литературу, в чём я также уверен).

Про магистерскую я надеюсь когда-нибудь рассказать в другом блоге. Вкратце, я научился кодировать в разрешимом подмножестве зависимой системы (брр, я столько раз писал это словосочетание, что муражки по коже пробежали) типов (Agda) некоторые любопытные утверждения о некотором ограниченном классе программ (подмножество систем управления чем-нибудь достаточно дискретным). Я всё мечтаю допилить это до состояния, когда этим можно будет хотя бы нормально поиграть, но в Агде очень не хватает deriving Eq для эквивалентности по Мартину-Лёфу, я экономил всё, где мог, а потому там пока всё не очень красиво и малоюзабельно (зато научно, ага).

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

Написание отчёта по госконтракту в TeXе это прямо веха в моей жизни, я считаю. Я так смачно натрахался с LaTeX2e, что словами не описать. По дороге возненавидел всё внутренности TeXа всей душой, но выпилил подобие ГОСТовских шаблонов для вёрстки документов и biblatex. Результатами я когда-нибудь тоже поделюсь (я хотел в сентябре, но, как обычно, времени допилить всё до приличного состояния нет, а в неприличном состоянии выкладывать стыдно). Нетипизированные языки программирования надо жечь.

Кстати, любопытно, в сентябре пришлось писать генерировалку doc'овских шаблонов для другого госконтракта. Из любопытства, возьмите достаточно большой вордовский документ, сохраните его в html. Загрузите обратно. За исключением изменения цвета текста (это баг ворда, да) вся разметка сохраняется. Даже ссылки на переменные и вычисляемые выражения в документе. Если почитать сгенерированный html и поэксперементировать с его минимизацией, то можно научиться генерировать красивые htmlные документы, в которых даже нумерация списков, оглавления и ссылки правильно генерируются самим вордом после их открытия им (правда в браузере их бесполезно открывать, вся разметка плывёт в жопу).

Я так нареверсинженерился того, что он там генерирует, что чувствую в себе силы написать компилятор из подмножества LaTeX в этот doc-html. Штука в том, что на этот раз я знаю как LaTeX устроен внутри и, извините, но компиляция документов сделанных при помощи стандартных пакетов и макросов LaTeX2e — занятие не для слабонервных. Если бы между texовским файлом пользователя и LaTeX2e был бы ещё какой-то вменяемый уровень абстракции, то ещё куда ни шло, но там сразу всё макроподставляется в грязнющий Plain TeX, полный всяких хаков, а это нереально декомпилировать обратно в адекватное описание того, что мы хотим получить. Судя по результатам реверсинженеринга, Word, в обмен на флексибилити, пытается держать внутри близкое к адекватному AST документа с которым хоть работать можно.

Короче, надо писать свой компилятор для TeXа.

Дальше. Я вроде писал, что у меня есть свой собственный дистрибутив. Так вот, был. Идея была хороша, из общего описания всех машин кластера генерируются squashfs-образы их систем, при пуске поверх squashfs при помощи aufs2 монтируется rwшный tmpfs. Чтобы закоммитить изменения нужно было запустить скрипт, который смонтировал бы ещё один tmpfs поверх, а предыдущий tmpfs зажал бы squasfsом, положил в специально отведённое место в /boot и добавил в смонтированные слои.
На практике, как оказалось, это работает не очень:
* локальные изменения перетирают изменения в настройках кластера и за конфликтами тяжело уследить (это можно было правильно победить, но лень);
* частые локальные изменения генерируют много слоёв в aufs, засирают неймспейс файловых систем в ядре;
* целиком пересобирать образы каждый раз очень бесит.
Я было стал переписывать систему, чтобы победить все эти недостатки сразу. Думал, думал, писал, писал, писал. И понял, что я пишу то, о чём уже слышал. Есть такой пакетный менеджер с очень неудачным трудно гуглибельным названием и операционная система, которая его использует. Мне лень тут пересказывать куски из его документации, читайте сами. Но эта штука решает почти все традиционные проблемы, связанные со сборками пакетов и деплоем.

По сути, Nix — это такой ленивый функциональный язык программирования, в котором есть специальный строгий тип derivation (по сути «пакет»). Эти деривейшоны (пакеты) генерируются из других деривейшонов (пакетов) функциями, принимающими зависимости (естественно, деривейшоны) пакета в качестве аргументов. Форс деривейшона — сборка пакета. Сборка происходит в изолированном окружении, где доступны только содержимые других явно указанных деривейшонов (аргументы функции). Никаких /usr и /usr/local в NixOS нет.
В итоге, забыть указать какую-то зависимость просто невозможно, пакет просто не скомпилируется. Идентефикатором деривейшона является хеш описания дерева зависимостей, начинающихся с него самого. Изменился исходник, способ сборки или зависимость — изменился идентефикатор.

Энвайромент юзера и системы явно составляются Nixом из списка нужных деривейшонов. Юзеры обычно делают это ручками (типа, мне нужен wget, я прошу Nix добавить мне его в энвайромент, если оно уже скомпилировано, то он просто его добавит, если нет, то скомпилирует и добавит, после этого, если другой юзер попросит добавить ему такой же wget (а не с другими зависимостями, например), то это произойдёт моментально), NixOS позволяет делать описание для всей системы, а nixos/modules по абстрактному описанию системы сгенерируют ещё и все конфиги в /etc и initrd (в том числе и конфиг для самого Nix, где рассказывают сколько ресурсов можно жрать во время сборки, например), например.

Можно откатываться на предыдущую версию пакета/всей системы, если что-то пошло не так (более того, версии системы добавляются в меню в GRUB и всегда можно загрузиться в предыдущую, если эту сломал), можно собрать две версии одного пакета, одну версию с разными зависимостями, установить пакет только для одно юзера (без прав rootа, кстати) и прочие плюшки, которые тут все просто не перечислить. Короче, Nix — это пакетный менеджер вашей мечты, просто вы этого пока ещё не знаете, прочтите их мануалы. Я в начале немного сомневался в удачности дизайна их системы, но, прочитав всю доступную документацию, понял, что там просто вещи не очень удачно названы (тот же «Nix» чего стоит, например, хрен выгуглишь), а по сути всё очень близко к идеалу. Настолько близко, насколько это вообще возможно без выбрасывания нафиг устоявшихся методов работы с системой (shell, не экзоядерное ядро, init, древовидная файловая система как таковая вообще, и без транзакций в частности).

Но и это ещё не всё, у них есть Disnix, который продляет эту логику на распределённые системы. Если у вас там какие-то сервисы друг от друга зависят на разных машинах, то оно даже обновлять и перезапускать их в правильном порядке будет. Чёртова магия.

Так вот, последние несколько недель в свободное время я хачил NixOS под свои нужды (как оказалось, там уже почти всё есть, хачил там-сям, по мелочи). Сделал ещё один уровень абстракции над nixos/modules, который из моего описания кластера генерирует отдельные описания всех машин для nixos/modules, а уже из них оно генерирует содержимое корня и всю ту шелуху, без которой юниксы не работают.

Сегодня, собственно, я закончил переводить последнюю машину в кластере на этот магический дистрибутив. На десктопе тут пока Arch, в универе Debian, но, я чувствую, что это ненадолго.

Фотография стенки рядом с центральным сетевым узлом в доме:
фотография двух сетевых свичей и модема
Стамегабитный свич полностью занят, в гигабитный воткнуты только те, кто делают между собой сетевой RAID1. На переднем плане чифтековский корпус одной из машин (6 винчестеров 3.5 + 3 пятидюймовых корзины для приводов, вместо которых тоже винчестеры), на нём внешний eSATA-бокс для винчестеров, не поместившихся внутрь. Между этим корпусом и стенкой стоит ещё одна машина с большим обёмом RAM, но всего двумя корзинами для винтов (я не хотел ещё один большой корпус, ставить некуда). eSATA-box подключён к ней. Также можно видеть зукселевский модем без крышки. На его CPU лежит чайная ложка, на микросхеме, отвечающей за WAN — десертная ложка на термопасте. Летом в них я воду кипячу. Остальные машины раскиданы по дому.

Если бы в моей деревне был нормальный интернет, то все свои хостинговые нужды я обслуживал бы сам :(

Что касается катания по Европе и последствий, то это самое вкусное, оставлю на следующий десерт. А в заголовке другого блога есть моя фотография из Франции, например.
|, me, hikki, ok

Мультиварка на Андроиде

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

Кстати, забавно, купить рисоварку на американском Амазоне, где доставка стоит дороже самой рисоварки, потом купить к ней коробку для переделывания 220 в 110 Вольт в России, а потом ещё переходник с обычной на полярную американскую розетку в Китае, получается дешевле, чем просто купить мультиварку в РФ. Если бы я аккуратнее поискал рисоварку откуда-нибудь из ЕУ, то можно было бы раза в два выйграть. Мне кажется, что это маразм какой-то. Мультиварки в РФ считаются элитной кухонной утварью, да?

Несколько месяцев назад сломался микрофон на моей Нокии 5200. Долго бесил окружающих возможностью общаться только смсками. Купил универсальную (!) гарнитуру для телефонов Nokia. С моим телефоном она работает только как наушники. Вау, ну ок. В порыве отчаяния купил Samsung Galaxy 580. Вот уже месяц не могу заставить себя начать им пользоваться как телефоном, потому что этот девайс явно считает меня за идиота, постоянно держа поднятое соединение по 3G, если воткнуть в него SIM-карту, и передавая все мои действия в ZOG Google. Зато гарнитура от Самсунга прекрасно работает с Нокией. Ад какой-то.

За этот месяц я немного поковырялся в Андроиде и многие вещи меня смешат.

Наблюдение первое. В самом низу у Андроида — Linux. Повыше — библиотеки на C, которые реально работают с железом, звонят, рисуют гуй, хранят базы данных. Потом гугловская виртуальная машина Dalvik. А потом уже весь тот хлам, что пишут простые смертные на Java.

Наблюдение второе. В Маркете приложений и правда дофига. Только они не нужны.
Большая часть популярных приложений добавляют функционал, который должен быть в поставке по-дефолту или фиксят баги базового функционала. Смержте это в базу, и они станут не нужны.
Остальную часть маркета составляют игры (мне не нужны, но фиг с ними), всякий треш типа Fart Apps, и, драматическая пауза, аналоги веб-интерфейсов для всяких сайтов.

Около года назад на лекции, посвящённой DSLям, когда речь зашла о классификации языков на DSLи и не-, я пошутил, что, может быть, однажды, очередная версия CSS станет Тьюринг-полной, позволяя манипулировать цветовыми ячейками произвольным образом, а потому рано отказывать себе в удовольствии называть CSS языком общего назначения. Я пошутил, а вселенная нет.
В HTML5 Canvas нет двойной буферизации и люди для игр на Java Scriptе изобретают велосипеды, частично перерисовывая области канваса. Почему-то мне это отчаянно напоминает конец восьмидесятых. Мир сошёл с ума.

Я люблю тихие девайсы со слабыми ЦПУ, а новый веб-интерфейс Твиттера любит четырёхядерные компьютеры. Постоянная 100% загрузка ЦПУ при пользовании веб-сайтом, с отключёнными глюкавыми плагинами типа flash — это теперь типа нормально, да? Мир сошёл с ума.

Но вернёмся к Андроиду. Очевидно, пользоваться веб-твиттером на телефоне невозможно, а добиться нормального отображения элементов управления любого сайта на экране с таким разрешением — тем более. Что делают разработчики Твиттера, Реддита, СлешДота, etc? Правильно, они выпускают приложение для телефонов, которое просто рисует юзабельный отзывчивый интерфейс на экране, и без лишних извращений с HTML, CSS, JavaScript, AJAXом и прочей веб2.0 хренью. Спрашивается, почему нельзя в обычные браузеры добавить песочницу, исполняющую какой-нибудь LLVM, после чего скомпилировать в этот LLVM какой-нибудь рендер от WebKit и Java Script VM, выбросить рендеринг HTML, CSS и исполнение JavaScript из самого браузера, оставив там только фетчер ресурсов, запрашиваемых песочницами, закладки, историю, рисование гуя и управление превилегиями? URLы даже можно было бы оставить как есть. Будет прямо как всеми любимый Андроид, только в браузерах. Или Андроид — это круто, но в вебе без веб2.0 и AJAX никак нельзя?

Когда я стал рассказывать эту мысль окружающим IRL, общую идею поддержали почти все, но стали холиварить, что вместо LLVMа надо Java-машину, потому что стековые машины рулят и работают везде, а регистровые — это трешак, и типа вообще Андроид рулит. Вопрос номер один: почему тогда в Андроиде Java, но с регистровой виртуальной машиной? Вопрос номер два: почему Java-апплеты не прижились? Вопрос номер три: почему в Java-машине постоянно находят глупые баги, типа переполнений?
Отвечаем. Стековые машины тормозят, интерпретировать их байткод ничем не лучше интерпретации Java Scriptа, для нормальной их работы нужен JIT, все современные компьютеры — регистровые, JIT из стековой VM в регистровую — сложный и багообразующий процесс.

Я считаю, что в Гугле это всё понимают, а API-интерфейс на Java — это просто маркетинг какой-то. Linux и драйвера — не Java. Библиотеки на C — не Java. Dalvik VM — какая-то совсем другая архитектура, а не Java. Транслятор из Java в байткод для Dalvik. Сверху API для Java. 90% системы ничего не знает о Java. Теперь покажем людям оставшиеся 10% и они будут плясать от радости, что можно и дальше киснуть мозгом на Java. Маркетинг ок. Мир сошёл с ума.

Ешё мне интересно, а чего боятся производители телефонов? Дайте мне драйвера от моего Самсунга, чтобы я смог звонить из программы на C и рисовать на экране, и через два месяца мне не нужен будет никакой Андроид, я сам всё нужное мне на Плюсах и Хаскеле напишу. Бред какой-то.
|, me, hikki, ok

Езда на медведях как метод объектно-ориентированного программирования

Сначала тут будет немного философских рассуждений о том, почему автомобили выиграли у лошадей, потом эти рассуждения обобщатся до какого-то маразма. После этого я снова что-то философское напишу о «паттернах проектирования», сдабривая это нарциссизмом. И только в самом конце я упомяну что-то конструктивное о том, почему у ООП имеются большие проблемы, на которые никто в ООПЦ (ООП Церковь) внимания почему-то не обращает.

После наболевшего от прожужжанных «паттернами» ушей ехидного предыдущего поста, последовавшего эпического срача в твиттере, поста zahardzhan и приезда сильно увлеченного объектно-ориентированными свистелками иностранного профессора, я даже на несколько дней засомневался в том, что адекватно воспринимаю происходящее, поскольку мои ответы на вопросы «что не так с X?» собеседников не устраивали. Однако, на прошедшей неделе я случайно для себя открыл замечательный метод рассуждений, позволяющий делать забавные умозаключения о современном state of art, и сейчас я немного их сюда повыписываю, стараясь аргументированно указать видимые мною недостатки.

Я бы рад снова начать с «паттернов», но ведь скажут, что я помешанный. Потому начну с (не) биологии. Итак.

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

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

Мне кажется, что в программировании наблюдается весьма схожая ситуация. Современный аппарат для доказательства корректности программ дорос до уровня, когда приложив немного усилий на самообразование, можно начать выигрывать на порядки во времени отладки. Число свойств, которые я не могу поручить проверить компилятору, уменьшается чуть ли не ежедневно. Но большинство программистов считает, что доказательства о программах — это к Дейкстре и Хоару, требуют много ручной работы, и там всё равно остаются ошибки (и зачем тогда стараться, да?). А адепты биологического подхода предпочитают все современные достижения просто игнорировать.

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

А после стали понемногу добавлять всякие «странные вещи», типа ADT, монад, Typeable, type families и индукцию по структуре (вместо неограниченной рекурсии). «Jonny the programmer» недоволен, как писать программы — непонятно, Джонни чертыхнулся и пошёл дальше писать на дотNet. Но те, кто таки поддался соблазну, внезапно обнаружили, что 80% полезных участков кода даже не требуют Тьюринг-полноты, а 19% из оставшихся не требуют отказа от строгости в типах (например, потому что они вдруг становятся рекурсивными). Да и вообще, плюсы вписывания всего, что только можно, в этот новый базис приятны: о программах можно автоматически (ыц!) рассуждать, можно их автоматически (ыц! ыц!) трансформировать (смотри, например, на трансформацию в векторные операции у Data Parallel Haskell), действительно сложные и неразрешимые вещи (IO и рекурсивные типы, например) можно чудесно изолировать и статически гарантировать эту изоляцию (то есть автоматически (ыц! ыц! ыц!) её проверять). Правда остаётся ещё один процент программ, где нужно очень аккуратно работать с ресурсами, или где всё действительно должно быть Dynamic и типы бесполезны, и обозначенные языки туда (пока?) лучше не совать.

Однако, оказывается, что эти «странные вещи» ещё и позволяют очень просто делать то, что раньше считалось сложным. Тут Джонни начинает крутить головой по сторонам, облизываться и требовать, чтобы и в его любимом языке дотNet появился вывод типов, и анонимные функции, и какие-нибудь монады, и ещё ADT, и ещё континюэйшоны, а теперь хорошо бы ещё и тайпклассы, да, да и это тоже было бы не плохо, и вывод типов (ой, он уже есть, но теперь есть тайпклассы и надо его сделать умнее), о, и ограниченные типы тоже хочу, и ещё нормальную редукцию мне, а не только макросы, и от зависимых типов не откажусь... В итоге, в погоне за упрощением методов выражения ограниченного класса типичных идиом, вместо solidного языка получается каша из фич, надёрганных из разных мест (например, делегаты и анонимные функции в C#).

Но Джонни теперь может в три раза короче описывать парсеры, так какие проблемы? Такие, что, если в язык, в котором было нельзя автоматически рассуждать о программах, добавить штуки, о которых можно автоматически рассуждать, то о языке рассуждать всё равно не получится. В общем, досыпали синтаксического сахара, а польза близка к нулю. Что же делать, если Джонни вдруг понял, что иногда уж очень хочется сбросить на компилятор однообразную работу.
— А! А давайте введём специальный тип модулей, в которых будем использовать только те инструменты о которых можно автоматически рассуждать! — в порыве энтузиазма восклицает Джонни.
— Мистер, ваше предложение означает, что эти модули вы будете писать на Haskell.
— Ой.

«Биология» в программах — это то, от чего хочется избавиться, но, это не значит, что «биология» — всегда плохо. Бывают программы, где выразительности современных систем типов недостаточно (двигатель всё время замерзает) и приходится/проще работать без типов вообще (гонять на собачьих упражках), или нужно очень мудро управлять ресурсами (есть только степь с травой и нет бензина), или, наконец, видимо есть какой-то ментальный барьер, стимулирующий для быстрой и грязной работы выбирать язык с утиной типизацией, а не со строгой. Другое дело, что по асфальту на собаках ездить глупо. И я вообще сомневаюсь, что бывают программы, которые не смогли бы ничего выиграть от доступа к нормальной системе типов. Иначе говоря, я сомневаюсь, что бывают программы, в которых все полезные свойства, которые хотелось бы проверить, неразрешимы.

Итак, если не запомните ничего другого.
* Eсли один и тот же результат можно получать биологически и автоматически, то второй вариант производственного процесса рано или поздно выигрывает.
* «Странные вещи» из функциональных языков хороши не тем, что на них коротко выражаются «паттерны», а тем, что о них можно автоматически рассуждать.
* Добавление этих «странных вещей» в существующие языки ничего полезного в этом аспекте не добавляют, поскольку, как правило, в этих языках уже достаточно мусора, о котором не получается автоматически рассуждать.
* Автоматические рассуждения о программах очень помогают писать хорошие программы. Доказывать корректность программ (в разумных пределах) намного проще и полезнее, чем об этом рассказывают.
* Сплошная «биология» — маразм, но выражать страшные вещи, не лезущие в известные разрешимые системы типов, иногда тоже хочется, потому от неё (пока?) никуда не деться.

А вот теперь снова про «паттерны».Collapse )
|, me, hikki, ok

Паттерны проектирования, гриды и прочая безответственность

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

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

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

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

В таком же смысле лямбда-исчисление и теория типов значительно проще, чем объектно-ориентированное программирование и паттерны проектирования. При этом, мне кажется, между первым—третьим и вторым—четвёртым куда больше сходства, чем может показаться на первый взгляд. В каком-то интервью (которое я не смог загуглить) вроде Simon Peyton-Jones говорил, что там, где ООП-кодеры начинают совать UML, хаскелисты расчехляют дополнительные стрелки в типовых аннотациях (вот ещё тред почти про это же на sof). Также и большинство паттернов занимается эмуляцией поведения шашечек из функционального мира (выборочно иду по часто упоминаемым из списка паттернов в Википедии): Adapter — замыкания, Interpreter — GADTs + eval, Listener (тут обман, его в списке в Вики нет) — замыкания, Mediator — ещё раз замыкания, Nullable — пахнет Maybe monad transformer, Proxy — тайпклассы и снова замыкания, Visitor — и тут снова тайпклассы. Ля-ля-ля, все всё давно поняли, а я — Капитан О.

Так вот, вернувшись на два параграфа назад, но глядя в список паттернов в Википедии (нет, там есть что-то осмысленное, но, в целом, один этот размер списка уже о чём-то говорит), нетрудно заметить, что эти паттерны проектирования — это философия какая-то, а совсем не математика. Конечно, философствовать куда приятнее, чем делом заниматься — сиди сочиняй себе паттерны. Частных случаев, выражающихся в случайной перестановке фич GADTs, замыканий, кванторов существования и прочей фигни высших порядков хватит на всю жизнь, можно не одну квази-интеллектуальную книжку по проектированию ПО написать. Тут же можно догадаться почему я там умолчал про всякие MV(C|.*).

В общем, наблюдается ярко выраженная любовь человечества к дисциплинам с огромным количеством мелких деталей, где можно строить из себя умного, вообще по сути ничего не понимая. В этом свете, любовь к преподаванию ООП на всяких «языках, используемых в индустрии», типа там C++, или Java, становится мотивационно оправданной: когда больше нечего сказать, можно пофилософствовать почему условие
(a < b) || (a == b) || (a > b)

для a и b целочисленного типа, может никогда не выполниться.

Надеюсь, я достаточно прямо выразил свою простую мысль: ООП, UML, паттерны и прочая «инженерия ПО» — это (за мелкими исключениями) философия, философия — не математика, программирование — математика. Любовь к такой философии легко объяснить отсутствием достаточного уровня абстрактного мышления, ибо ковыряться в деталях всегда проще, чем построить общую теорию. А работать-то не хочется.

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

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

В заключение хочу отметить, что со времени последних постов, полных уважения к философии, я пришел к выводу, что всякие философы, любители UMLя, паттернов и прочей мути — вовсе не вредны для общества. Смотрите сами, если бы по мгновению волшебной палочки вдруг все фишеры и спамеры исчезли из сети, то люди так расслабились бы, что появление очередного вида мошенничества могло бы вызвать катастрофу глобального масштаба. Философия, РАЕН и ООП с паттернами просто необходимы обществу, чтобы у адекватных его членов не скисли мозги.
|, me, hikki, ok

Страшное программирование: управление ресурсами

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

Вообще, я считаю, что все утверждения бывают либо ложными, либо очевидными (либо я ещё не понял, что же тут написано, ок). В внутрискобочном случае, если сегодня я не понимаю почему прочитанное не ложно, но и не очевидно, то я добавляю текст в группу закладок браузера, которые я перечитываю round-robinом. Эта группа закладок сейчас содержит ~400 элементов, а повторное чтение через полгода-год обычно приносит таки ощущение очевидности и утверждение из начала параграфа также остаётся очевидным.

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

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

Зато существует некто ivansorokin, с которым мы частенько встречаемся на ддр-паде или в метро по дороге к таковому. И, видимо, кроме того, что эту светлую голову иногда посещают какие-то очень похожие (только в императивном базисе) на иногда посещающие меня мысли. Эта светлая голова ещё и решает более прикладные задачи, чем моя, потому поболтать о всяких инженерных вещах бывает очень весело. И, да, голова всё пишет на хорошем C++ (с бустом и гимназистками), а моя для себя — на Haskell, а остальное — на чём придётся.
Результат обмена опытом обычно попадает в одну из следующих категорий:
* идея, дующая из очередного драфта C++xx, после преобразования базиса, превращается в знакомые функциональные алгебраические структуры (что не удивительно, но весело. например, сравните r-value ссылки с move-семантикой и линейные типы, концепты и тайпклассы);
* я узнаю что-то интересное из истории развития фич в плюсах;
* находится что-то, аналогов чему в знакомых теориях я не знаю, но о подходах к реализации чего можно поспорить.
Обмен опытом в обратную сторону идёт с большим трудом, ибо рассказывать о том куда ещё можно воткнуть себе какие-нибудь комонады, чтобы стало веселее, как-то грустновато, зато я могу рассказать о куче глупостей из области операционных систем.

Один из самых частых топиков болтовни — всякие частные случаи, обработка исключительных ситуаций, «правильный и красивый» менеджмент ресурсов и тому подобное.
На этой почве я тут внезапно осознал, что программирование — это черезвычайно хитровывернутая область. Сейчас я хорошенько покапитаню.
* Мы (люди) не умеем хорошо программировать синхронные системы, а замахиваемся на асинхронные.
* Не можем поработить одноядерный ЦПУ, а замахиваемся на многоядерные. Рассуждаем о масштабируемости различных классов задач на «более 48 ядер», а даже для одного ядра написать компилятор, адекватно минимизирующий кеш-миссы не способны.
* Не можем оседлать самый простой метод менеджмента ресурсов — RAII, а вовсю используем сборщики мусора и прочие «высокоуровневые» механизмы.
* И так далее, и тому подобное.

По поводу предпоследнего мне пришёл в голову простой, капитанский, но забавный пример.

RAII придумали, в том числе, чтобы явно не вызывать деструкторы, освобождающие ресурсы. Так? Ну логично, сконструировал — занял у системы чего-то, собрался помирать — отдай.
Мега кусок а-ля C++/Python кода:
foo = connectSocket("tcp:127.0.0.1:1234");
/* вторая строчка */
bar = socket2Iterator(foo);
foreach (elem in bar) {
    cout << elem;
}


Пусть тут socket2Iterator берёт сокет, и делает из него что-то итератороподобное (например, генерирует ленивый стрим строк, считанных из сокета).
Очевидно, что RAII тут — крутая тема. Если при конструировании что-то сломалось, то объекты будут деструктурированы в нужном порядке. Все счастливы.

А что, если в цикле, при выковыривании очередного элемента из bar, сокету foo станет плохо и система отберёт от него этот ресурс (принудительно закроет сокет)? Адекватных варианта два:
* эксепшн, закатили стек вверх до обработчика, он, если ему надо, повторил операцию с начала, или сделал что-то более адекватное на своё усмотрение;
* делимитед континюейшн до обработчика, обработчик пытается восставновить валидное состояние сокета (реконнект или что там надо), чтобы код мог ехать дальше, не заметив ошибки, получилось — вернули управление назад, едем дальше, не получилось — сворачиваемся.

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

Аналогичная ситуация _всегда_ возникает в деструкторе bar (bar всегда деструктурируют до foo), если foo стало плохо. Не вызывать деструктор bar вроде как нельзя, оно может само занимать какие-то динамически выделенные ресурсы, но что делать, если этот деструктор обратится к невалидному foo?

А что, если освобождение ресурса может свалиться с ошибкой «попробуйте позже»? А оставлять ресурсы занятыми нельзя.
А что, если объекты можно создавать не только последовательно, а у них там какие-то весёлые графы зависимостей друг от друга?

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

Тут-то и появляются всякие смешные правила о том, как надо обрабатывать исключения в деструкторах, или забывают о RAII и делегируют управление ресурсами коду сверху, появляются очереди на освобождение ресурсов, начинают выделять ресурсы регионами, etc, etc.

Не то, чтобы я утверждал, что всё описанное нерешабельно или черезвычайно сложно. К чему это я капитаню? Забавно же. Хотели очень простую ресурсную управлялку, где у объектов бывает только валидное состояние или вываливаемся в обработчик ошибок, вроде всё хорошо делали, инварианты сохранять научились, а при первой же работе с внешним ресурсом обломались.
«Ладно», — говорим мы и выбираем способ менеджмента покруче. Но тут оказывается регионы и сборщики мусора вносят недетерминизм во время жизни объектов, что не всегда можно делать (потому, например в Java, приходится, по сути, явно вызвать деструкторы у всяких там сокетов, что ещё веселее: объект в памяти ещё зачем-то есть, а ресурса системы уже нет). Остаётся ручное управление? Привет, 70-тые года.

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

Тут одни умные дядьки подумали, и решили, что надо всё верифицировать, а другие решили, что срочно пора изобретать Haskell и явно разруливать побочные эффекты. Окей, теперь с «чистым» кодом проблем нет, да ещё можно автоматом его параллелить. Только вот, если потерей производительности на иммутабельных структурах данных можно пожертвовать, винчестер можно превратить в придаток оперативной памяти, а на монитор выводить последовательность проекций чистой функции, рисующей UI, то, клавиатура и сетевая карта всё-равно никуда не делись, и управлять ими как-то надо (если только не начать считать всю сеть однородным компьютером, что, по очевидным причинам, вряд ли произойдёт).

Для каждого конкретного случая съедобное решение придумать можно, общего никто не знает. Известный учёный муж Conal Elliott много пишет, придумывает функциональное-реактивное программирование, об описанной проблеме говорит, но ничего конкретного не предлагает. Все чего-то такое говорят, что всё сложно, а ничего конкретного не предлагают. Я в этом усматриваю какую-то несправедливость.
Жизнь такая очень интересная штука (если P ≠ NP, иначе — не такая уж и интересная). Где даже в самых мутных областях есть хоть какой-то заметный прогресс. Например, говорят, что продуктивность программистов удваивается каждые шесть лет (я, например, где-то читал, что первый компилятор Фортрана съел аж 50 человеколет, а сегодня подобный проект дают в качестве (не самой сложной) курсовой работы). Инструменты всё круче, мощнее, веселее. А управление ресурсами в каменном веке. Печаль.
|, me, hikki, ok

Военные девайсеги

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

Во-первых, ко мне уже хрен знает сколько месяцев назад приехал тачскрин для Eee PC вот в такой коробочке:


В комплекте:
* тачскрин,
* USB-хаб и всякие проводочки,
* ручка-перо;
* какой-то CD-диск.

Я его даже в течении недели после его приезда установил в сам тысячный eee. Пока разбирал-собирал девайс поимел много радостей, поскольку эти китайцы инструкции на английском пишут так, что уж лучше бы иероглифами писали. Нет, правда. Что имелось в виду в подписи к какой-то картинке, я понял только тогда, когда ощутил на себе, что если бы я сделал «иначе», то количество головной боли при сборке уменьшилось бы в разы. А потом я понял, что это «иначе», было зашифровано как раз в той непонятной надписи.

Однако, присобачить сам экран удалось на удивление хорошо: ни пузырьков воздуха, ни пылинок между LCD и тачскрином не осталось, потому радость.

Касательно схемотехники, оно втыкается в eee черезвычайно просто:
* от материнки отрывается хвост камеры (разъём типа нано-USB);
* вместо камеры ставится USB-хаб (из комплекта);
* камера втыкается в хаб, туда же втыкается тачскрин;
* в оставшиеся разъёмы хаба втыкаются произвольные USB-девайсы (через дополнительные проводочки).

Результат выглядит так:


Сама панель производства eGalax, и, как обычно, единственная проблема в линуксе — драйвер. Там есть проприетарный и даже работающий, но его явно писали какие-то идиоты, потому что оно работает только с конкретной версией ядра и умеет намертво вешать иксы. Но, в принципе, пользоваться можно.
Я нашёл какой-то патч к ядру, делающий опенсурсному драйверу хорошо с панелями eGalax, но проверить его у меня пока как-то руки не дошли.

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


В остальном, тыкать пальцами или пером в экран достаточно весело. Рисовать, правда, не очень удобно, ибо в руках весь девайс держать тяжело, а «на весу» с открытым экраном рисоваки кривые получаются.

Систему для сборки образов Archa из того поста допилил до вменяемого состояния. Сделал DSL на питоне (потом, наверное, сделаю специальный chroot для бутстраппинга и перепишу DSL на хаскеле, но пока что не хочу держать 100+ мегабайтный ghc на образе диска, который без ghc занимает всего 150 метров) для автоматической генерации конфигов для каждой машины по описанию всего кластера.
Ещё есть забавная идея заменить даже sh/bash/etc скрипты, используемые при запуске системы, на хаскелевский eDSL. Благо система позволяет, ибо набор софта на кластере ограничен и переписать весь sysinit с печеньками на хаскель я осилю. В качестве профита можно получить статическую проверку всего и вся, в сто раз уменьшить количество кода в скриптах и не тестировать в виртуальной машине всевозможные варианты запуска, до деплоя на реальную машину, чтобы не наткнуться на синтаксическую ошибку в какой-нибудь редко-используемой части init-скрипта (эта особенность раннего initа, написанного на bash, просто невыносимо бесит. пропустил где-то кавычку и система умерла ещё до монтирования дисков. как хочешь — так и исправляй).

Тешу себя надеждами, что этот же великий дистрибутив можно будет портировать и на eee.
|, me, hikki, ok

Игрушки

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

От большой любви к железкам купил ещё 4Гб памяти, интелловскую гигабитную сетевую карту, асусовский гигабитный свич и клавиатуру Sven wireless 9004 (о которой, в данный момент, имею весьма двойственные впечатления, но с кровати рулить компьютером — ок).

Происходящее вокруг заставляет думать о вещах, о которых мне думать очень не нравится, и, к тому же, абсолютно не оставляет свободного времени. А так хочется уйти в анимушный запой на неделю.
В не очень свободное время парю себе мозг представлением (автоматного, да) eDSLя на хаскеле при помощи всяких там стрелок и категорий. Глубина научного достижения невелика, перспективы смутны, но немного пахнет FRP, а это сейчас модно. Такие дела.
|, me, hikki, ok

Надо что-то делать

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

Новая железка состоит из Intel DQ45CB, Core 2 Duo E7600, 4 Gb RAM, смешной корпус Foxconn, смешной кулер CoolerMaster, HDD Hitachi на 2TB.
Раз я уж начал, называть машины из домашнего кластера именами персонажей из Cowboy Bebop, то этот получил имя «ein».
Такую забавную материнку выбрал из за чипсета Q45, у него есть VT-d (хочу IOMMU и проброс девайсов в виртуальные машины) и хардварное декодирование HD видяо. Правда под лялихом оно пока не очень поддерживается, но vaapi подаёт надежды. Сначала хотел взять с чипсетом G45 (оно vaapi поддерживается целиком), но тот без VT-d, а это не так весело.
Мать сама оказалась всем хороша, кроме просто невозможно бажного биоса. В каждом обновлении одно чинят, а другое ломается, сейчас отвалился хардварный мониторинг %_%.
И ещё оно E7600 не поддерживало до первого обновления чудесного биоса, потому пришлось выковыривать ЦПУ из другого компьютера, перепрошивать биос (что само по себе было достаточно весело), и только потом юзать новый проц. У ASUSов, хочу заметить, мать запускается и на неизвестных ей CPUID. Бутлоадер не грузит, но хоть биос обновить можно без шаманства.

Collapse )

Что касается линуксов. В общем, появилась у меня бредовая идея сделать не просто кучу компьютеров, а нормальный мейнфрейм, чтобы все грузились с одинаковых образов. Но дом — не датацентр и все компьютеры должны немного отличаться в железках (а потому и в софте), иначе каждый из них как бы бессмысленный, ибо белки сворачивать у меня желания нет.
ein у меня вообще есть желание поставить к телевизору, но образа у всех хочу одинаковые.
Потому моя гениальная мысль заключается в том, чтобы всё, что можно, унести в виртуальные машины (с дисками расшаренными по сети, на случай фейла одной ноды), а всё что нельзя (ибо оно должно работать напрямую с железкой, например) — совать в бранчи aufs2, отпочковывающиеся copy-on-write от основного образа.
Основной образ я сначала было хотел слепить из Debian Live, но узрев миллион строк кода в livehelper я эту идею отложил. Следующий хорошо мне известный дистрибутив — Arch.
За три дня выходных я:
* изучил всю доступную документацию по Arch (чем сэкономил в следующие два дня уйму времени);
* изучил то, как работает larch (Live Arch), понял, что оно мне не нравится и надо писать свой;
* поигрался с утилитами из Арчевых dev-tools, где есть mkarchroot (типа debootstrap от Дебиана), понял что это близко к тому, что надо, но тоже надо написать свой;
* написал свои «правильные» версии утилит из dev-tools, позволяющие быстро собирать произвольные Арчевские образы в chroot, рут которого может находится на aufs2;
* написал свои хуки mkinitcpio, делающие aufs2 root при загрузке системы, слегка переписал rc.* скрипты, чтобы они не пугались такого метода загрузки;
* заставил всё это работать.

Итого:
* собираем chroot с Арчем;
* вваливаемся в этот chroot с пустым rw бранчем, на который ставим необходимые модификации;
* получаем ванильный Arch внизу и модификации на другом лейере, которые система видит как общую файловую систему;
* сжимаем все бранчи в отдельные файлы при помощи squashfs;
* кладём эти файлы в специальную директорию в /boot;
* хук в initrd подхватывает эти образы при загрузке и восстанавливает из них рабочий / с rw слоем на tmpfs.
В результате можно использовать один ванильный образ на все компьютеры, с маленьким образом локальных модификаций. При этом никакой NFS-root не нужен, работает это быстрее чем по NFS, и вообще даже сеть не нужна, можно иногда только базовый образ, получаемый упаковкой в squashfs chrootнутого ванильного Archа, обновлять хоть с флешки и радоваться.
Надо ещё только допилить, чтобы rw бранчем при загрузке можно было ставить раздел диска/lvm2, а то это тоже может быть полезно иногда.

И есть ещё глупый вопрос по математике: вот не вполне понятно почему сигнатуры алгебр иногда содержат нульарные функции, которые, казалось бы, выражают объекты, которые должны быть элементами множеств над которыми эти алгебры растут. Когда это F-алгебра и теория категорий, то эти нульарные штуки (ну там они уже даже и не функции, а эндофункторы с доменом из ко-произведения с терминальным объектом, но это не суть важно) воспринимаются чисто как технические ограничения (потому что есть объекты, но нет множеств, а, например, нейтральные элементы группы надо как-то выражать), но в аксиоматике теории множеств нульарный нейтральный элемент среди «функций» выглядит странно. Чего я не понимаю? upd: сам разобрался, ок