Category: it

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

Vash

Как натолкнуть косу на камень

Bitcoin хранит всю историю транзакций в блокчейне. Персистентность блокчейна -- одно из базовых свойств технологии. Любой человек может провести транзакции, и любой человек может проверить, что таковые действительно произошли.

Идея заключается в том, чтобы закодировать в блокчейне магнет-ссылки торрентов. Результат:

1. Лол, ну попробуйте теперь их оттуда убрать.
2. Ну давайте, признайте теперь биткойн экстремистской технологией.

UPD. Конечно же, я не первый человек, которому эта идея пришла в голову.
UPD. Даже уже написали!
Vash

Отрывочно про веб

Добрый вечер+03:00, дорогой читатель. Сегодня я хотел бы поговорить про веб-разработку.

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

Все, наверное, слышали, про такую игру как испорченный телефон. Она описывает именно то социологическое явление, когда изначально правдоподобные данные становятся абсурдно не похожи на оригинал в процессе передачи информации по цепочке людей. А вы слышали доклад Уильяма Танниклифа в Канадской государственной типографии в 1967 году? Я вот не слышал, и даже не смог найти стенограмму. Но почему-то считается, что именно Танниклиф был первым, кто сформулировал принцип разделения представления и содержимого, используемый сейчас для того, чтобы оправдать разделение HTML и CSS.

Если я правильно понимаю, то в этой трактовке за представление отвечает CSS, а за содержимое — HTML. Любой здравомыслящий читатель, способный разделить логичные суждения от собачьего бреда, понимает, к какой категории отнести эту мысль. HTML не отвечает за содержимое.

За него отвечал бы XML, если бы веб вовремя перешёл на XSLT. Да, сейчас ещё есть следы от начала развития XML в вебе: есть XHTML, есть processing instruction xml-stylesheet. Проблема в том, что из JS на странице оригинальный XML стандартным образом получить уже нельзя. Скорее всего, такой подход исключил бы необходимость во всех этих MV*-фреймворках, которыми пестрит веб. "Скорее всего" потому что XSLT Тьюринг-полон, и многие вещи, которые бы мы ожидали видеть происходящими автоматически, вроде сохранения фокуса на input при обновлении XML-DOM, уже не были бы доступны. Всегда можно было бы сделать well-behaved подмножество, но в этом направлении все полимеры уже просраны.

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

Кстати, даже несмотря на то, что широко распространено мнение, что CSS не Тьюринг-полон, это, скорее всего, не так. Учитывая, что даже крайне простые вещи вроде Rule 110 полны, представляется крайне сомнительным, что в CSS с жирной как тюлень спекой нельзя найти хоть какой-нибудь вычислительный контекст. Комитет стандартизации явно и недвусмыслено с этим борется, конечно, поэтому я потратил добрых 16 часов на поиск такового контекста, подготавливая материал для этого поста, но так и не смог привести рабочий пример. Где-то так же обстоит ситуация с тем, что комитет стандартизации С++ явно пытался сделать так, чтобы порядок объявлений не влиял на семантику программы, но нихрена у них не получилось. Даже частные члены класса можно без всякого undefined behavior воровать. Впрочем, вот, как обстоят дела.

CSS явно сделан так, чтобы пройтись по списку всех правил один раз, не возвращаясь обратно. Типичная идея well-founded recursion. Проблема в том, что это относится только к ядру языка.

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

  • Во-вторых, мы можем воспользоваться селектором focus. Если исчезает поле, на котором стоит фокус, то он переходит к следующему полю, и стили пересчитываются. Если возможно сделать так, чтобы focus циклически перемещался по набору полей, до Тьюринг-полноты рукой подать. Этот подход заработал не так хорошо, как мне бы хотелось, потому что в разных браузерах работал по разному. В Chrome все поля теряли фокус, а в Firefox фокус с точки зрения CSS стоял на невыделенном поле. Разобраться, как это должно работать, я так и не смог. Может, кто-то из вас осилит этот собачий бред.

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

  • Наконец, есть media query, которые позволяют получить ширину окна. Засовывая media query внутрь iframe мы можем получить размер обрамляющего элемента, а это означает, что у нас появляется возможность зависеть от результата вычислений CSS наружного документа. Если при этом возможно было бы настроить потенциально бесконечное количество вложенных iframe, то мы получили бы Тьюринг-полноту. Впрочем, этот подход станет намного ближе, когда появятся element query.

Подводя итог: и почему нельзя было бы просто сделать нормальный язык программирования?

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

  • А что, HTML не переиспользуется?

  • А что, если бы язык был один, то часть определений нельзя было бы закешировать?

Обычно после этих двух вопросов этот аргумент отпадает. Остаётся ещё один, относительно более серьёзный: так что мне, повторять style на каждом элементе, как это делалось в раннем вебе (cellspacing помните)?

А почему бы и нет? Давайте писать стиль на самом элементе. Вас не устраивает, что стили будут встречаться более одного раза? Code reuse падает? А что обычно делают люди, чтобы с этим бороться? Вводят бесчисленные селекторы? Или, может, всё-таки переменные, функции и, на худой конец, классы? Функции в случае HTML представить себе очень просто: все серьёзные веб-разработчики так или иначе уже пользуются шаблонами.

Что вы там раньше использовали, миксины в SASS/SCSS? Не напоминает наследование? Не напоминает про ФВП? Так зачем городить дополнительные абстракции, если всё делается старыми добрыми приёмами императивного и функционального программирования?

JS, конечно, тоже бесит. Этот ублюдок Эйха имеет ровно одну положительную сторону: красивый способ работы с событиями. Всё остальное там омерзительно: и коэрции с перегрузками, и прототипное наследование с return в конструкторах, где нельзя сделать прототип функционального объекта, кроме как стандартный Function, и где не работает нормально typeof, который вообще хорошему языку не нужен был бы. Оптимизации хвостовых вызовов нет. Зато есть JIT, работу которого понимают только разработчики, а почти все остальные программисты, даже из команды Google Closure, продолжают настаивать, что это панацея, и что JIT волшебно решит неразрешимую задачу и оптимизирует любой код.

Бесит то, что вообще что-то нужно писать. Я, например, люблю сидеть за компьютером ночью в тёмной комнате. Сейчас так и делаю, кстати. И вот, передо мной интерфейс ЖЖ с чистым белым фоном, освещающий всю чёртову комнату. Ребята, мне глаза режет. Что, прикажете каждому сайту имплементить систему смены фона?

Подобного рода проблемы решались и ранее. В Windows почти все кнопки, независимо от программы, рисуются одинаково, и это зависит от темы. Строки вроде "OK" и "Отмена" в текущей локализации прописаны в user32. Короче говоря, программе позволяют избавиться от того, что можно настроить и общесистемно.

Почему же тогда сайты не начнут отдавать просто API? Уже просто по описанию функций, которые доступны в API, легко понять, как это должно выглядеть в интерфейсе. Для сложных сайтов можно добавить какие-нибудь легковесные рекомендации по их выводу. Ответов два:

Во-первых, до сих пор нет нормального стандарта на веб-API. REST крайне тяжеловесен и не позволяет делать вызовы с сервера на клиент. WebSocket ничего не говорит про формат отдельного пакета (хотя уже моменты вроде binary/text формата сообщения говорят, что WS это дерьмо, но об этом дальше). Хорошо работает связка WebSocket + ProtoBuf, правда, формат сообщений всё равно приходится описывать. Правильно это выглядело бы просто как одно общее приложение, где лежит код клиента и сервера, и где компилятор сам придумывает всю логику позади вызова c клиента метода, определённого на сервере, и наоборот. Для этого нужно, чтобы клиент и сервер были написаны на одном языке, а генератору нужна статическая типизация. Cерверный JS уже есть, статическую типизацию, наверное, может дать TypeScript.

Во-вторых, уже есть попытки делать что-то подобное. Все хотят пострелять по лягушкам в Германии лазером из космоса со спутника, создавая микроформаты, RSS/Atom, semantic web, pubsubhubbub, OpenID и прочие микроскопически частные способы делиться чем-нибудь относительно структурированным, не замечая леса за деревьями.

Отдельно хотелось бы поговорить про существующие протоколы. Вот вы читаете этот текст. Вы читаете его в исходном виде, или это уже его представление? Вы ведь не можете воспринимать напрямую номера символов, так? Любой текст на компьютере это представление данных в человекочитаемом виде. Тогда объясните, почему у протоколов вроде HTTP тот факт, что они обмениваются "человекочитаемым" текстом, вызывает предоргазменное состояние у их разработчиков? А сделать GUI поумнее нельзя? Ну ладно, вы можете утверждать, что текстового редактора вам достаточно. Ну сделайте стандартный редактор деревьев или стандартизируйте наконец-то формат описания протоколов, чтобы редактор мог подтянуть из файла или сети биекцию бинарного представления и текста, в чём проблема?

Отдельно гадок сам HTTP. Всем известен принцип single responsibility. Почему тогда HTTP занимается запросом страниц, отправкой данных, хранением персистентного состояния на клиенте (cookie), авторизацией, перенаправлениями, отчётами об ошибках всех сортов и ещё кучей всякого дерьма, полное описание которого даже в один RFC не влезло (7230-7237)? Изначально этот протокол вообще должен был использоваться для того, чтобы можно было редактировать страницы веба напрямую в браузере, что потом напрочь забыли, а недавно присунули какой-то нерабочий contentEditable взамен.

Не понятно вообще, зачем делать всякие URL и e-mail текстом, и потом морочиться с его разбором (ой, нерегулярный язык!), если можно это было сделать деревом, и потом его автоматически (де)сериализовать.

Анонимность, криптографические подписи и P2P тоже должны входить в состав новых стандартов веба.

Я вижу только один выход из сложившейся ситуации.

  1. Всё это говно полностью отправляется на помойку.

  2. W3C бойкотируется.

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

  4. В первую очередь решается, как сделать так, чтобы никакие решения не уходили в legacy. ProtoBuf показывает хороший пример.

  5. В качестве основных языков веба вводятся байткод с содержимым по типу LLVM и статический язык программирования без небезопасных конструкций, но и без GC, JIT и прочих тормозов. В первый компилируются другие ЯП, которые люди хотели бы использовать для веба, второй используется по умолчанию.

  6. Программам на этом языке выдаются разнообразные API, в первую очередь -- canvas, заменяющий HTML.

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

  8. Для существующих браузеров предоставляются расширения, позволяющие ходить в новый веб.

  9. Если кто-то не хочет расширения, тому выдаётся HTML с Asm.js, полученный в результате компиляции чем-то вроде Emscripten.

Vash

Товарищи попросили составить опросник для программистов на C#

Я слышал от отдельных людей, что C# крайне роляет, поскольку там есть полиморфная рекурсия и прочее бесполезное блядство. К сожалению, у меня не хватило времени на то, чтобы составить полный его (блядства) список, поскольку он практически нескончаем. Оказывается, тут один товарищ весьма деликатно, в диалоговой форме предложил ответить на пару вопросов о том, где же это блядство роляет лучше всего. Собственно, вам оный пройти и предлагаю.

Оригинал взят у __diogen__ в Товарищи попросили составить опросник для программистов на C#
Я, естественно, не стал отказывать хорошим людям.
Collapse )
Vash

options = options || {}; или обращение к говнокодерам на JS

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

Ребята, зачем так делать? Я понимаю, что упоротые по никсам программисты не получают никакого когнитивного диссонанса, говоря про unix way и single responsibility, делая программы с туевой хучей аргументов командной строки, и потом пытаясь через man man понять, как ими пользоваться, через history вспомнить, как это, блядь, делалось, и через лишний пробел в rm почистить себе весь диск. Но должны же быть адекватные люди, да?

Ребята, этот подход не модульный. Вы никогда не вынесете в опции всё, что мне хотелось бы пофиксить внутри вашей убогой библиотеки. Зачем, зачем вы продолжаете это делать? У вашего кода слишком маленький memory footprint? Он слишком мало тормозит? JIT слишком хорошо понимает, как убрать оттуда весь дохлый код, которого у вас там 90% для отдельного применения либы?

Ботайте, блин, Хаскелл, делайте комбинаторы, экспозьте API из элементарных запчастей, пусть пользователь собирает.
Vash

Как заставить node-gyp таки работать

Node.js использует для модулей, написанных на С++, ублюдочный пакет под названием node-gyp. Ублюдочный он потому, что авторам глубоко посрать на все операционные системы, кроме их любимой убунты.

Ни разу не видел, чтобы node-gyp заработал под виндой с первого раза. Три самых частых его бага:

1. Переменной окружения PYTHON не должно быть. Она по дефолту ссылается папку с Python, node-gyp от этой наглости входит в ступор и вылетает. Зачем ему питон, спросите вы? Да потому что ублюдок джаваскрипта и С++ просто обязан внутри использовать скрипты на тормозном питоне. (Посмотрите, например, на билд-скрипты Google Closure.)
Проверка: %PYTHON% в cmd должен говорить, что такой переменной нет.
Как исправить: set PYTHON= (и ничего после знака равно) перед тем, как вы будете делать npm install <пакет>.

2. Если у вас, не дай боже, что-то кроме iso-8859-1 в имени пользователя, то node-gyp работать не может, потому что они не умеют работать с юникодом. Переименовать пользователя будет недостаточно, потому что папка пользователя, в которой Node.js хранит настройки, будет называться всё так же. Создайте нового пользователя, убедитесь, что ваше VPN-подключение к Интернет расшарено на всех пользователей, и делайте действия оттуда. Ну или подправьте имя папки в реестре и на диске руками, на свой страх и риск.

3. Если у вас стояло много версий Visual Studio, и зачем-то одну из них удалили, то есть шанс, что node-gyp попытается откомпилировать именно ей. Подотрите остатки от студии и удалите соответствующую переменную окружения VSxxCOMNTOOLS.

Если всё это не помогло, то вы внимательно читаете логи, смотрите, какой конкретно пакет node-gyp не сумел скомпилировать, качаете его исходники в отдельную папочку npm'ом, правите, делаете npm link из этой папки. Теперь возвращаетесь на то место, где должен быть этот пакет в устанавливаемом, делаете оттуда npm link <имя пакета>, и всё!

И да, если ваc это достало так же, как и меня, напишите этим дебилам, что они дебилы.
Vash

ChromIE

Авторы Google Chrome потрясли меня сегодня своим интеллектом, последовав пути IE, и воткнув в обход W3C крайне раздражающую фичу в виде XSS Auditor. Я использую сервак с закрытыми исходниками, который ажаксом подтягивает код со скриптом, и где я не могу воткнуть нестандартный заголовок. Теперь у меня не работают скрипты. Спасибо, Google.

Пришлось адский воркараунд совать, добавляя скрипты картинками, и засовывая CSS внутрь JS.

UPD Олимпиадный привет ЛГБТ-движению весьма ясно даёт понять, почему всё так. Потому что пидарасы.
Vash

10+ причин почему не стоит цитировать глупости love5an.

В ответ на.

Так как вопрос использования С++ для меня уже давно неактуален, поскольку оный был изучен на достаточном уровне, чтобы не захлёстывал баттхёрт при столкновении с фрагментами языка, которые оказывались в первое время нелогичными, но в боях с тов. love5an в своё время было потеряно немало нервов, я ограничусь только лёгким комментированием, без применения своевременных и адекватных мер к его последователям.

Дискуссии длились несколько лет, и у меня никак не найдётся возможности полностью передать всю их глубину и содержательность. Откомментировал только то, что смог разобрать. Если остальное мне кто-нибудь объяснит и конкретизирует, буду рад обсудить. Также слегка откомментировать взялся мой коллега shuffle_c.
>> медленная компиляция
Медленная компиляция была, в основном, когда я работал с Boost. Причины для этого другие, а именно неоднократный препроцессинг одних и тех же файлов, а также устаревшие метавычисления на шаблонах. Впрочем, эти проблемы решаются свежими расширениями языка. Функции времени компиляции, объявленные с ключевым словом сonstexpr, отрабатывают существенно быстрее. С появлением вариадических шаблонов огромное количество определений шаблонов с разной арностью также потеряло смысл. Правда, boost ещё не переписали, но это, как я понимаю, вопрос поддержки свежих фич компиляторами. В любом случае, жаловаться на медленную компиляцию в языке, где вычисления времени компиляции тьюринг-полны, и используются для чего-нибудь вроде генерации парсеров (boost::spirit) довольно абсурдно.
sh: Precompiled headers очень существенно увеличивают компиляцию, почти как в C# получается. у нас в проекте они не используются, но и то я не сказать, что жалуюсь на скорость.
>> частые «internal error» в компиляторах
Даже несмотря на то, что я, в своё время, эти самые С1001 в студии выискивал и докладывал в ЖЖ и в багтрекер, я бы не сказал, что их так уж много. Если искать их намеренно, скажем, в Glasgow Haskell Compiler, то уже довольно простой пример из TaPL с экспоненциально растущими типами во вложенных let переполняет память и подвешивает компилятор.
>> код плохо читается и его сложно поддерживать
А уж код на ранее упомянутом Haskell и подавно. Почему-то никто не вменяет это плохому дизайну языка. Или я просто не слышал? Если серьёзно, то учите С++. Прочтите стандарт хотя бы.
>> разбор кода различными инструментами, вроде IDE, и его генерация - сильно затруднены
В общем-то, проблемы авторов IDE. AFAIK, VS2013 весьма неплохо с этим справляется. Хотите подсвечивать синтаксис? Есть Winnie Colorizer. Необходимые знания для написания своего аналога подтягиваются из задания PA1 курса CPPGM. Проблема, скорее, в компетентности программистов. Генерация кода на С++ не нужна, поскольку там есть средства метапрограммирования из коробки. Впрочем, у меня с генерацией тоже проблем не было. Писал транслятор из лиспа в шаблоны.
sh: Даже VS 2012 с этим хорошо справляется, Visual Assist тоже очень хорошо начал. А скоро ожидается тулза от jetbrains, так что этот вопрос почти закрыт.
>> ручное управление памятью
Основная причина для его введения -- правило zero overhead. В языках со сборкой мусора обычно тяжело избавиться от нежелательного поведения сборщика. Обычно мы имеем overhead по производительности и прочие опасные эффекты, что для системного программирования попросту недопустимо.
sh: GC, по факту, возможна, благодаря поддержке со стороны языка в С++11. но, по факту, она никому все равно не нужна. Ручное управление это хорошо, потому что приемы управления используются не только для памяти, а для любых ресурсов
>> утечки памяти
Наверное, отстал от технологий, но неужели автоматическая сборка циклического мусора перестала быть проблемой? То есть, конечно, она описана ещё в драгонбуке, но методы-то не эффективные, или порождают слабые ссылки, или не параллелятся, или ещё что-нибудь такое. Может быть, я открою кому-нибудь глаза, но задача своевременной сборки мусора вообще алгоритмически неразрешима, и люди пользуются субоптимальными решениями. Разве искать причину утечек легче во внутренностях рантайма, чем в своём коде?
>> висячие ссылки
NullPointerException?
sh: weak_ptr
>> сегфолты
Продолжить предложение: “Разница между ошибками, генерируемыми ОС и рантаймом, заключается в том, что…”
Впрочем, у меня такого почти не бывает. Наверное потому, что я использую STL, а не CRT.
>> стандартные средства, как то malloc/new, работают медленно
Потому что используют вызовы ОС. Нужна скорость -- используйте placement new. Кроме того, в С++ никто 1) не использует malloc; 2) не запрещает перегрузить new на более эффективный.
sh: Медленно -- не аргумент. в других языках, что ли, быстрее?
>> Никакого ABI
Использование С++ на многих платформах подразумевает, что наличие, к примеру, строго заданного порядка следования аргументов на стеке или endianness приведёт к тому, что использовать язык на разных платформах будет нельзя. Для этого там есть соответствующие прагмы, __declspec, naked функции и прочая. Не понимаю, как можно 1) говорить, что у языка нет ABI, учитывая, что ABI задаётся платформой; 2) говорить это про крайне кроссплатформенный С++. Под ABI подразумевалось что-то другое?
>> Нестандартизированный и непредсказумый name mangling
>> Дублирование функционала Си
Обратная совместимость. Дублирования нет, поскольку использование функционала Си в С++ is highly discouraged. С тем же успехом можно говорить, что есть дублирование функционала ассемблера, поскольку в большинстве реализаций есть возможность делать ассемблерные вставки.
>> запутывает новичков
Новичков запутывают плохие книги и плохие преподаватели. Любому новичку, использующему гугл на уровне падована, сразу удаётся найти что-нибудь вроде вот этого списка (http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list), где использовать const char *, scanf и printf никто не посоветует.
>> препроцессор - шаблоны
Вы всё ещё вспоминаете ту одну первобытную реализацию С++, где шаблоны инстанцировались посредством текстовой подстановки фактических аргументов в их тело?
>> указатели - ссылки
Ссылки это синтаксический сахар для некоторых применений указателей. Арифметика указателей нужна для написания эффективного кода, и назвать эти два средства языка дублирующими друг друга нельзя.
sh: r-value ссылки при этом имеют совершенно иную семантику.
>> структуры - классы
Они не дублируют друг друга. Структуры и классы различаются спецификатором доступа по умолчанию.
>> stdio - iostream
сstdio предоставляет нетипизированные средства для ввода-вывода и в С++ не используется.
>> Отсутствует даже такой функционал, как вменяемая работа со строками и многомерные массивы
Для строк есть string. Для всего остального есть boost, являющийся полигоном для расширений стандартной библиотеки языка. Многомерные массивы там есть. Из boost в STL этот функционал не перенесли, поскольку научились не делать поспешных решений, и предпочитают сначала подумать над вводимыми в язык возможностями. На все возможности времени комитета стандартизации не хватает.
sh: чем vector<vector… не многомерный массив?
(Полагаю, дело в затратах на хранение дополнительных размерностей для jagged массивов, если автор задумывался о zero overhead, в чём я сомневаюсь.)
>> Юникод
wstring, codecvt?
>> Слабая типизация
“Слабая” это прилагательное, а не термин. Действительно сильная типизация есть только в небольшом наборе языков вроде Coq, где можно получить гарантии об отсутствии практически любого вида нежелательного поведения в программе на уровне системы типов, т.е. во время компиляции. Если вы про то, что указатель можно разыменовать, так, извините, и в сильно типизированном Haskell я могу использовать unsafe-функции или определять функции с неполным pattern’ом со схожими эффектами.
>> const не дает абсолютно никаких гарантий
Адекватные люди не используют const_cast просто так.
>> практически никакой интроспекции
Zero overhead.
>> передача объектов по значению
Кто хочет передавать по значению, пусть передаёт. Обычно передают как const &. Конструкторы копирования предоставляют все возможности для управления владением ресурсами. Есть RAII. О чём речь?
>> проблема ромба по дефолту не разрешается никак
Виртуальное наследование. По дефолту -- пути наследования. Почему не виртуальное наследование по дефолту? Zero overhead.
sh: по дефолту, если это и проблема - она тут же вылезет, а как исправить, нужно уже знать - не просто же так ромб делается
>> исключения в конструкторах гарантированно влекут утечку памяти
Вообще-то исключения в конструкторах это вполне обычное дело. Как влекут?
>> деструктор можно вызывать до выхода из блока кода, или до delete
В общем-то, проблемы человека, который делает это, не зная, зачем это нужно (а нужно это как раз для использования всяких placement new, где компилятор не способен вызвать вовремя деструктор автоматически, поскольку не отслеживает местонахождение объекта).
>> pure virtual function call
Проблемы кривизны рук.
>> деструкторы обязаны быть виртуальными
>> по дефолту - не виртуальные
Zero overhead.
>> никаких интерфейсов, только классы
>> порядок инициализации статических членов классов не определен
При наличии в конструкторах сайд-эффектов, зависимых друг от друга, объект-обладатель темпорально первого эффекта должен управлять обладателями последующих. Обычно делается через наследование. Порядок инициализации не нужен.
>> private, public и protected не дают никаких гарантий сокрытия данных
Нужно абсолютное сокрытие данных? Криптографически аппаратно разделённые области памяти и криптографически стойкий интерфейс до монитора?
>> отсутствие «свойств»
Свойства, мутаторы и прочее дерьмо из джавки в С++ переносят джависты. В самом языке для этого есть классы, конструкторы приведения типов, перегрузка операторов приведения типов. Создаётся один раз тип наподобие “число не более 5”, создаются поля этого типа. При присваивании полю значения 6 отрабатывает проверка в конструкторе, выбрасывается исключение. Code reuse существенно возрастает. Я об этом, кстати, уже писал. http://udpn.livejournal.com/59975.html
>> «friend» нарушают инкапсуляцию
Ключевое слово friend нужно для реализации вещей вроде множественной диспетчеризации, для трюка Бартона-Накмана и прочих полезностей.
sh: «public» нарушают инкапсуляцию, что же делать?
>> [шаблоны] километровые и плохо читаемые сообщения об ошибках при компиляции
static_assert добавлен в язык. Разработчики библиотек, связанных с метапрограммированием, увы, должны с такими сообщениями мириться, пока не создана IDE, позволяющая отлаживать compile-time.
sh: Я не знаю, можно ли аппелировать к опыту, но как правило от этих сообщений нужно только место, где оно произошло.
>> [шаблоны] обязаны содержать реализацию в заголовочных файлах
Использовать заголовочные файлы в С++ это моветон. В С++ используются файлы .hpp, которые представляют собой попросту вынесенные блоки кода. Впрочем, всё равно ведь вы неправду написали, там есть extern template.
>> [шаблоны] позволяют генерировать некорректный код
Т.е. нужно убедиться в том, что тьюринг-полная система сгенерирует правильный код? Не кажется, что задача алгоритмически неразрешима?
>> отсутствие finally/unwind-protect
Или вкратце: в С++ для этого есть RAII.
>> заставляет городить классы ради одних деструкторов
Вопрос структурного программирования против объектно-ориентированного, в общем-то. Если лень заводить классы, используйте функции.

Резюме: лучшая стратегия на авторском уровне познания языка формулируется как "заткнись и пиши".
Vash

Обобщённые стрелки

Предупреждение: дальше по тексту зачастую будет утверждаться какое-нибудь X, однако никаких исследований по этому поводу не проводилось никем и никогда. Поэтому вопросы вроде "c чего ты взял, что Х -- обобщённая стрелка", скорее всего, останутся с ответом "потому что попой чую" или вовсе без оного.

У вас есть некоторый язык программирования.
Вы хотите в нём воспользоваться имеющимся синтаксисом для некоторой хитрой цели.
К примеру, вы кодогенерируете джаваскрипт.
Вам нужен, таким образом, способ перегрузки оригинального синтаксиса.
Существуют языки, где вы можете получить AST некоторого фрагмента кода, поменять его и сделать обратно кодом. Например, Лисп, Хаскелл и Скала.
Такую возможность называют "макросы", саму дисциплину -- метапрограммирование.
Писать AST вручную, если мы что-нибудь генерируем, неприятно.
Нам хотелось бы иметь возможности из почти исходного синтаксиса генерировать неполные AST (c дырками).
Такая возможность называется квазиквотированием.
Но что-либо серьёзное в этом ключе написать всё равно сложно.
Не вполне понятно, в каком именно месте здесь включается типизация, например.
Удостовериться, что данный фрагмент кода генерирует AST с корректными типами всегда, невозможно.
Для этого придётся проводить что-то вроде статического анализа над генерирующим AST кодом.
Учитывая, что используется оригинальный язык, а он обычно Тьюринг-полон, получаем неразрешимую задачу.
Доказывать корректность таких кодогенераторов в общем случае сложно.
Это "вжжж" неспроста.
Рассмотренный ранее подход к метапрограммированию называется интенсиональным.
Существуют ещё и не-интенсиональные подходы, и я знаю из них только один.
Обобщённые стрелки.
Для них в общем случае нужна поддержка интерпретатором или компилятором.
Программа при трансляции переводится в язык из небольшого набора комбинаторов.
Пользователю предоставляется возможность эти комбинаторы переопределять на некотором фрагменте кода.
Чтобы всё было в порядке, комбинаторы поставляются с набором аксиом, которым они должны удовлетворять.
Теперь к подробностям.
Разные программы требуют различного набора комбинаторов.
Если в программе есть несколько переменных, её представление требует комбинаторов, которые работают с парами (типами-произведениями), например, first : (a -(x)> b) -> ((a, c) -(x)> (b, c)). Этот first должен удовлетворять кое-каким аксиомам.
Если одна переменная может использоваться дважды, нужен dup : a -(x)> (a, a).
Если в языке есть литералы целых, нужно что-то вроде int : () -(x)> Int.
Чтобы появился этот (), нужен ещё набор примитивов типа uncancel_l : a -(x)-> ((), a), uncancel_r : a -(x)> (a, ()).
Ну вы поняли идею, да? Шинкуем язык на комбинаторы и типа всё.
На самом деле, мы можем нашинковать исходный язык на комбинаторы многими способами.
Например, если в языке мы можем объявлять рекурсивные функции, то мы можем добавить комбинатор fix, он же loop.
В то же время, если бы в нашем языке была возможна только "хорошая" убывающая рекурсия по натуральным числам, мы могли бы объявить в качестве примитива natrec.
Но ничто нам не мешает иметь и то, и другое одновременно.
Просто данный код будет транслироваться в потенциально разные наборы комбинаторов в зависимости от того, акие комбинаторы мы перегрузили в данном фрагменте кода.
Например, факториал будет иметь возможность транслироваться в natrec, если мы запускаем его в доказанно завершимом контексте, или fix, если мы запускаем его в контексте трансляции в JS.
И ещё: наборы комбинаторов это type class'ы.
Ознакомиться с классическими можно, изучив (необобщённые) стрелки: Arrow, ArrowChoice, ArrowApply, ArrowLoop
Этих наборов целая решётка.

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

Стрелки (необобщённые) были разработаны, в том числе, для создания эффективных парсеров (Swierstra & Duponchel). Дело в том, что стрелка a ~> b это что-то вроде функции a -> b или около того, но она дополнительно может хранить какие-нибудь данные.
data Something a b = Something AdditionalData (a -> [b])
Это, кстати, позволяет решить одну очень больную проблему для других языков.
Представьте себе, что вы можете произвести некоторые затратные вычисления при запуске программы, а потом пользоваться результатами. Например, посчитать таблицы синусов для дальнейшего использования в генерации объёмных сферических объектов или меш нужной детализации по функции, как это делают в демо-сценах
Вы затем хотите вынести этот функционал в библиотеку и обнаруживаете, что не знаете, стоит ли вам вызывать эти вычисления (обычно в конструкторе соотв. класса), так как вы не знаете, будут ли они использованы в пользовательском коде.
Можно сделать это в стиле синглетона, но это породит +1 if (и лишние +5% прочистки конвеера), а также в исполнимый файл может попасть код, который никогда не будет вызван (оптимизатор может его и удалить, но он не тотальный, задача поиска мёртвого кода неразрешимая же).

Самое главное: обобщённые стрелки позволяют создать действительно универсальный язык.
Обычно когда в языке X не хватает Y, кто-нибудь берёт и делает X+Y.
Например, с чего бы от С++ ответвляться всяким PHP?
Нужна была весьма специфическая среда для кода (хорошие встроенные строки, например).
В то же время, несмотря на почти идентичность синтаксиса, в язык были внесены изменения.
Теперь библиотеки для С++ нельзя просто так взять и использовать в PHP и наоборот.
В случае языка со встроенными обобщёнными стрелками нужно было бы просто создать подходящую стрелку, которая работает с server state, session state и чем-нибудь там ещё.
Скорее всего, для такой стрелки не понадобилось бы даже менять компилятор.
Вся кодовая база была бы доступна. Весь старый синтаксис бы работал.

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

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

Инстансы:
хост-язык (этот инстанс неявно скармливается функции main)
парсеры
кодогенераторы (fix генерирует рекурсивные вызовы, let генерирует заголовки функций, ...)
    CUDA
    шейдеры
    JS, CSS, HTML, PHP
    С++
    заголовки .h для dll сразу из определения функций
    VHDL и Verilog
    электрические схемы (цифровые и аналоговые)
    изображения (векторная графика, генеративное моделирование, SVG)
специализатор (упрощает pow(x, 2) до \x -> x * x)
инлайнер
оптимизаторы
неявное распараллеливание
трансляторы

Хотелось бы поблагодарить ребе akuklev за разъяснение мне этого дела, камрада tomotom за то, что не устаёт слушать мой больной бред и гуру sharpc за лучи ненависти к ФП и стратегию "заткнись и пиши" :)