Невеяло видео:
Что бесит программиста | Анастасия Лукьяненко
Ravens - Intelligent Rascals of the Skies | Free Documentary Nature
Если ворон сумел освоить тачскрин, то скоро его наймут писать софт для андроида. Ну или хотя бы веб-приложухи на JS.
Если серьезно, то мне не дает покоя недавнее обсуждение сложности отдельных конструкций в ЯП:
programming languages performance benchmarks (комментарий)
Там были упомянуты вопросы сложность рекурсивных функций и циклов. Как вы можете знать, на базе рекуррентных функций строятся такие замечательные вещи, как сеть Фейстля и подстановочно-перестановочная сеть, составляющие основу большинства симметричных алгоритмов шифрования. То есть, даже хорошо обученный и оснащенный человек не может ускорить вычисление конечно рекуррентной функции, не может угадать, что получится через несколько шагов или какие отклонения от нормы привели нас к состоянию текущего цикла вычисления функции.
Важное наблюдение — цикл можно представить в виде простого рекурсивного вызова (функция может вызывать себя только один раз), и простой рекурсивный вызов можно представить в виде цикла. Еще более важное наблюдение: машину Тьюринга можно представить как рекуррентную функцию, которая принимает аргументом предыдущее состояние машины и выдает на выход следующее состояние машины. Следствием этого являются известные вам алгоритмически неразрешимые задачки, как то проблема остановки, определение свойств произвольного алгоритма-функции (теорема Райса).
Асимметричные криптографические алгоритмы, которые зачастую основаны на модульной арифметике, как то RSA и эллиптическая криптография, являются типичными рекуррентными алгоритмами с глубокой степенью вложенности, пусть это и выражено в ввиде хитромудрых модульных операций умножения и возведения в степень, при этом входные и выходные значения алгоритмов имеют одинаковый размер, то есть, как конечное состояние машины Тьюринга на предыдущем и текущем цикле.
На основании этих исследований я хотел бы сформулировать теоремы Byko3y: для произвольного нетривиального алгоритма, представляющего собой неограниченно рекуррентную функцию, то есть программу машины Тьюринга, справедливы утверждения:
- если программа успешно отработала на одном наборе входных данных, то нет никакой гарантии, что она успешно отработает на другом наборе входных данных;
- для достаточно сложной программы нет способа узнать, где произошла ошибка на прошлых циклах вычисления, если у нас есть только состояние текущего цикла вычисления;
- машина Тьюринга — кусок дерьма с плохо предсказуемыми свойствами.
Есть ли выход из Тьюринг-западни? То есть, существуют ли/можно ли создать инструменты, на которых сможет достаточно эффективно писать даже умственно осталая мартышка? Очевидно, есть Тьюринг-неполные языки, которые просты и достаточно мощны для некоего узкого набора задач. Регулярные выражения, SQL, в конце-концов подмножества обычных ЯП, или какая-нибудь Clojure, построенная на персистентных структурах данных с очень хорошей предсказуемостью поведения и ограничением применения макросов. Даже Rust в каком-то смысле тоже попытался пойти именно по этому направлению, то есть, через ограничение применения изменяемого состояния, характерного для Тьюринг-машины.
Очень долго индустрия приходила к замыканиям, но замыкания хороши именно тем, что избавляют нас от сложной работы с общим изменяемым состоянием, и становятся плохи, когда замыкания начинают принимать/передавать аргументами другие замыкания и вызывать таким образом сами себя, создавая сложное рекуррентное поведение.
Или когда пользователь хочет отсортировать некий массив или даже банально посчитать сумму, ему совсем не обязательно писать цикл, ему не нужно проходить по массиву последовательно от первого элемента до последнего — исходный порядок здесь не имеет значения. Но Тьюринг-машины научили нас, что действия должны выполняться строго последовательно, и нынче никто уже никто не ставит под сомнение такой подход. Функциональные языки, даже весьма «чистые», имеют функции reduce, но я не видел еще ни одного языка, который имел бы реализацию reduce, безразличную к порядку прохода по элементам, вроде иерархического агрегирования аки агрегатные функции в SQL.
Одна из относительной свежих попыток решить эту проблему для разработки фронтэнда — React.js. Не Angular, который значительно сложнее и мартышку за него не посадишь, а именно React, который если и тьюринг-полон, то эту тьюринг полноту непросто достичь. С позиции программиста-пользователя React, имеет тупейше прямолинейное преобразование данных в отображение, и такую же простую функциональность для измения состояния по событиям пользователського ввода, причем, механизм «ввод->изменение модели» развязан с механизмом «модель->данные», и оба они развязаны между отдельными компонентами, потому косяки реализации мартыхой одного компонента не рушат другой.
Продолжайте список, какие инструменты/приемы вы знаете или о каких вы думали/мечтали.
PS: давно хочу вкатиться в ограниченное подмножество C++ без наследования, без зубодробильных шаблонов, с минимумом исключений. Потому что на Си неудобно писать без обобщений и замыканий. Буду благодарен за литературу и/или готовые опенсорсные проекты, реализованные в подобном стиле. Знаю, что Unity сделан в этом духе, но беда в том, что Unity проприетарен.