Как стать автором
Обновить

Вам следует написать новый (ужасный) язык программирования

Уровень сложностиПростой
Время на прочтение5 мин
Количество просмотров15K
Всего голосов 45: ↑43 и ↓2+55
Комментарии63

Комментарии 63

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

На самом деле хорошая мысль, тоже время от времени пишу в стол свои небольшие ЯП, интересно продумывать их архитектуру.

Я писал свой ЯП :-) И он был ужасен, да. Причем, во многом - намеренно ужасен. Для системы мониторинга okerr был создан язык Sequence. Идея в чем - программный код для проверок (например, запущен ли systemd сервис, сколько места на диске, есть ли бэкапы с таким-то именем за последние сутки, какой load average) должны подгружаться с центрального сервера, а он - не доверенный. ( например, вы доверяете apt/dnf установить пакет, когда вы это захотели, но не доверяете же ему самому устанавливать что он хочет и когда хочет, так же и агент окерр на системе должен быть заведомо безопасен). С одной стороны, подгрузка кодов с сервера - хорошо (можно прямо на сервере из удобного UI нарулить что хочешь, скажем, перенастроить проверки для дюжины серверов и сервера начнут репортить новые метрики).

Однако, пользователь okerr не хочет же, чтобы код с чужого сервера мониторинга мог писать файлы на своем сервере? Не хочет даже чтобы он мог читать лишние файлы. Более того, не хочет чтобы проверка могла войти в вечный цикл!

Вот и пришлось написать этот уникальный язык, на котором нельзя сделать вечный цикл. Читать файлы можно (но интерпретатор должен заранее получить в аргументах список разрешенных для чтения файлов, прочитать другой файл, не из этого списка не получится). С одной стороны, язык получился в какой-то мере функциональным (им можно узнать размер свободного места на каждом подмонтированном диске, например), с другой - он получился mostly harmless, мне сложно даже вообразить, чтобы на нем можно было написать какую-то "вредную" программу. Заметьте - там не было циклов, никаких там for/while! Но при этом он мог (к примеру) выдать метрики по свободному месту для произвольного числа подмонтированных дисков (там была итерация по конечному списку).

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

В общем, со временем пришлось признать этот опыт неудачным. Язык получился некрасивый, писать на нем тяжело и неприятно. Хотя со своей задачей он справлялся, но не столько ценно это оказалось. Может быть для управления сотнями серверов это было бы оправдано, но в таких случаях обычно есть всякие ansible.

Так что теперь в okerr используется очень простая схема - каждый скрипт проверки пишет на STDOUT свои данные, скрипты можно делать хоть на bash, но все скрипты локальные. Пример (провека la для Load Average):

# okerrmod --dump la
NAME: mx:la
TAGS: la
METHOD: numerical|maxlim=2
STATUS: 0.12

Все стало ну очень просто и легко и понятно. Писать проверки - тоже одно удовольствие и быстро делается.

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

Кажется, для подобных штук просто DSL разрабатывают, либо, вообще, задают конфигурацию в JSON/YAML. Зачем там именно язык?

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

Задумка была в том чтобы получить "безопасный пайтон (perl/shell/php)". Вам нужно написать, допустим, свой собственный код проверки, специфичный для вашего сервера/приложения, вы его пишете, загружаете на сервер мониторинга. А клиентский код на ваших серверах (которые вы мониторите) обращаются к [недоверенному] серверу мониторинга, выкачивают код проверок и запускают у себя.

Это все можно было бы сделать на том же пайтоне, но в этом случае требуется большое доверие к серверу (сервису) мониторинга. Что если там через уязвимость другой клиент взломает ваш аккаунт, поломает эти ваши скрипты и вставит в них "rm -rf / "? Что если сами админы мониторинга так вот похулиганят? Это риск, а я сам параноик, и понимаю, когда клиенты такие же. Поэтому вот и захотелось язык для этого. Но во многом это было не каким-то "бизнес-требованием" а именно собственным смелым интересным авантюрным экспериментом.

Вот пара скриптов на sequence для понимания степени ужасности:

SET DIR=/var/lib/okerr/backups
SET RE=.gz
METHOD numerical minlim=10240
TAG backup
DIR path=$DIR maxdepth=2
FILTER type=="REG"
GREP field=basename re=$RE
FILTER mage<86400
REPLACE field=basename search="\d{8}" replace=DATE dest=tplname
GROUP key=tplname max=ctime
FORK
NAME $_name:backup:$tplname
DETAILS $basename: $size bytes
FORMAT $size
NAME $_name:df
METHOD numerical maxlim=80
TAG df
DF
FILTER not ('/media/' in path or '/var/lib/docker' in path)
FORK
EXPORT path=path
NAME $_name-$path
DETAILS $percent% ($usedg/${totalg}G used, $freeg left)
FORMAT $percent

безопасный пайтон (perl/shell/php)

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

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

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

На самом деле они используют не монструозную виртуальную машину со сбрасываемым состоянием после каждого запроса. Зачастую эта виртуалка запускается прямо в браузере.

Ха! А мы создали свой язык (интерпретируемый) для управления координатником. Я всё собираюсь написать статью про это. Вещь примитивная, но отчаянно полезная.

Я придумал уже 3 ЯП, один из которых применяется в металлургическом производстве. Второй - для описания музыки текстом. Третий ориентирован на математические вычисления с расширенным набором операторов. И ни один из них не кажется мне ужасным)

О! А можно поподробнее, причем про все три? Очень интересно! Или уже есть в ваших публикациях?

Про описание музыки текстом - по идее есть Lilypond (и можно придумать разные варианты), но традиционный нотный текст двумерен, а обычный текст - одномерен - по сути всё есть строка, и это кажется главная причина почему Lilypond не очень-то востребован (может кроме как промежуточный формат, типа midi).

Статьи на эту темы вряд ли будут в обозримом будущем, но в комментариях неоднократно упоминал. Для музыки - нужен для моего ДСП-процессора и хочется попробовать неравномерные темперации (это когда в частности до-диез не равен ре-бемолю). Для математики - стало не хватать Вольфрама и хочется свести количество скобочек к минимуму, что достигается вводом дополнительных операторов умножения и деления с другими приоритетами. Например sin x pi + cos x pi. Или a+b//c+d вместо (a+b)/(c+d). Параллельное присваивание a,b=a+b,a-b. Определение (и приведение) типа справа, как в паскале x=1:quaternion.

По работе - надстройка над SQL для описания логики обмена данными (в обе стороны) между контроллерами Simatic и СУБД.

Ага! Спасибо! Очень интересно! Статьи таки хочется.

Про язык для музыки - очень интересно! А как вы его применяете? Можно пример кода?
Мне как программисту и музыканту это крайне интересно.

Пока никак не применяю, поскольку он появился совсем недавно и существует пока что только в виде черновой спецификации. Всё началось со статьи @shiru8bitпро его проект 1tracker, где он обобщает редакторы трекерной музыки и придумывает свой (текстовый) формат для описания и хранения трекерной музыки. Ну а цитата " трекер — это неудобный интерфейс с высоким порогом вхождения" вызвала желание подумать о том, а можно ли попроще и пониже, а не просто наследовать сложившиеся традиции. Помимо этого, у меня уже достаточно давно в разработке SDK для визуального программирования DSP, который я делаю поочёредно на двух языках (c++ и c#), наследуя идеи NI Reaktor, но с намного более высоким уровнем ООП-абстракции, включая возможность описывать граф обработки чисто текстом и ничем не ограниченную модульность. Первым делом реализовал спектр-анализатор с произвольной длиной (а не только 2 в степени), и быструю свёртку с нулевой задержкой. Затем появилась поддержка VST, там и VSTi, играть соло с клавиатуры быстро наскучило и захотелось иметь возможность быстро накидать басовую партию и какой-нибудь пэд на фоне. Писать полноценный нотный редактор я не готов, а вот распарсить текст вполне реально, поскольку опыт парсинга мат. выражений и гитарных табов уже есть.

Музыкальное образование у меня классическое (хоть и не долгое), учился по нотам с русскими названиями. Это было основной причиной, по который lilpond и прочие меня не впечатлили. Ну а дальше исходил из "максимально удобно" и "максимально читаемо" (куда MusicXML очевидно не подходит). Отдельным интересом было продумать запись цифрами в табулатурном стиле (типа 0 4 0 7 0 5 0 8 на первой струне гитары) и так, чтобы это не противоречило общей концепции. Похожим образом хотелось реализовать и партии ударных - визуально понятный паттерн, который можно запустить в цикле без необходимости копирования во все такты партитуры, как в типичном нотном редакторе. Да и так в целом сейчас мало кто пишет в стиле Баха и современная музыка состоит из коротких повторяющихся отрывков, которые незачем прописывать много раз в явном виде.

Я не приступил к реализации сразу, чтобы язык немного "отлежался" и его можно было бы критически осмыслить и доработать без необходимости переписывать кодовую базу. Также осталась парочка спорных моментов, с которыми я еще не смог определиться - например, в одном случае для паузы удобно использовать символ "_", а в другом - ".". Но точка уже присутствует в классической нотной записи для увеличения длительности ноты, и например Guido Music Notation её так и использует. Другой момент - я хочу избавиться от явного задания октавы в ноте (потому что это замусоривает текст и вообще хотелось бы иметь возможность транспонирования, в том числе и по диатонической, а не только хроматической гамме), а для этого нужно задавать перескоки через октавы, в чём тоже есть несколько вариантов (в частности, ми и +ми отличаются сильнее, чем 0 и +0, поскольку мы привыкли к тому, что плюс перед числом ничего не меняет, а ++ вообще инкремент). Ну и с нестандартными темперациями тоже не всё понятно (типа 22EDO), и особенно неравномерных. Возможно, что не стоит упираться в ASCII и использовать уже наконец расширенный набор символов из юникода. Тогда ↑ вместо + будет трактоваться более однозначно.

А пример кода - как-то так в минимальной комплектации:

Собачий вальс
[Собачий вальс]

@key:Gb
@octave:4
@duration:1/4

((ми ре)/2 соль {си +соль}x2)x2 
 (ми ре)/2 соль {си +соль} -ми
 {си +соль} -ре  {до фа}х2 
((ми ре)/2 -ре {до фа}х2)х2
 (ми ре)/2 -ре {до фа} -ми
 {до фа} соль {си +соль}x2 
 . соль {си +соль} -ми
 {си +соль} -ре {до фа}х2  
 . -ре {до фа} -ми
 {до фа} соль {си +соль}x2

Поначалу, наверное, буду делать экспорт в MIDI, чтобы результат можно было открыть в нотном редакторе в привычном графическом виде и быстро проверить. А вот наоборот, из MIDI в текст будет сильно сложнее, особенно с многоголосными дорожками и арпеджированными аккордами. Но желание сделать это тоже сильное.

Почему 3 новых языка, а не 3 бибилотеки или фреймворка для уже существующих языков?Всё равно ваши языки никогда не сравняться по возможностям и удобству использования с существующими развитыми языками.

Так ЯП - это же не обязательно самодостаточный компилятор, а в первую очередь синтаксис и грамматика. Я читал Страуструпа и знаю, что си с классами компилировался в си, и пошёл тем же путём, только в c#, в котором описывается вся необходимая инфраструктура. Когда-нибудь потом и c++ подключу.

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

Я пока что единственный их пользователь, сам с собой как-нибудь найду компромисс.

Третий ориентирован на математические вычисления с расширенным набором операторов.

Значит я тоже как-то однажды подобный язык изобрел: https://github.com/KvanTTT/MathExpressions.NET 😊 Правда после опыта работы над компилятором Kotlin мне скорей всего он покажется ужасным, с учетом того, сколько вещей я в нем не продумал.

Да, я помню ваши статьи, они классные.

Я уже более чем 8 лет разрабатываю свой язык программирования. При этом ужасным я бы его не назвал, даже наоборот - я его отточил до весьма приятного в использовании состояния и реализовал язык настолько безопасным, насколько это возможно.

Поначалу правда он действительно красотою и удобством не блистал, но со временем я всё больше его улучшал. Сейчас по ряду аспектов он может уделать многие существующие общеупотребительные языки.

Уже показывали миру?

Давно уже. У меня в том числе и на Хабре есть публикации по нему.
Компилятор доступен на моём github.

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

Прикольная штука, но зачем оно мне, я на этом работать не буду... и т.п.

ещё было бы неплохо создать язык для создания языков -- какие-то огрызки есть типа генераторов парсеров, языков с pattern match типа F#/Haskell но именно полноразмерного языка позволяющего декларативно описать полный стек компилятора, и набор библиотек для реализации рантайма и основных фишек различных языков...

Такие генераторы давно существуют. Я даже держал в руках одну тоненькую книжку:

Построение интерпретаторов и компиляторов: Использование программ Bizon, Byacc, Zubr / А.В.Костельцев

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

т.к. новый язык будет репликацией того языка, на котором этот язык разрабатывался

большинство интерпретаторов современных языков (не все) написаны на С++, но далеко не все на него похожи же, верно?

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

и обязательное посещение compiler.su

Спасибо за статью, ностальгия), в конце 80х, в школе, писал игры для Агата на ассемблере, надумал написать язык для написания игр, даже название придумал: LFG - language for games, но ... "институт, экзамены, сессия" )

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

К сожалению 99% нынешних программистов даже о своем фреймворке не помышляют, воспринимают то что придумано другими такими же программистами, как некие непреложные аксиомы и законы физики. А любые шаги более любопытных коллег в сторону, брезгливо называют "самописками" и велосипедами.

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

Как вариант придумать свой процессор что будет выполнять команды и язык под него. Сейчас это просто, сначала виртуально, а потом перенести на FPGA демоплату за 20$ типа такой с Алиэкспресса "Sipeed Lychee Tang Nano 4K".

Всё так, но принесёт много знаний любой сложный проект.

Что мне не хватает в С++ и что хотел бы видеть в своём языке:

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

-возможность скомпилировать только то, что нужно сейчас. Тоже больше зависит от компилятора.

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

-нет вектор.resize_to_range(), и не только в С++. Приходится вручную удалять спереди и сзади.

-pop_back() не имеет параметра в виде количества выкидываемых элементов, хотя это напрашивается. Может, такое есть в других языках?

-также странно, что у функций нет имени возвращаемого значения. Вы знали, что printf возвращает количество выведенных символов? Незнание этого мне стоило велосипедов в своё время. Если же имя возвращаемого можно было посмотреть так же, как и имена параметров, то такой ситуации не возникло бы.

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

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

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

-также странно, что у функций нет имени возвращаемого значения. Вы знали, что printf возвращает количество выведенных символов? Незнание этого мне стоило велосипедов в своё время. Если же имя возвращаемого можно было посмотреть так же, как и имена параметров, то такой ситуации не возникло бы.

А что значит имя (в данном случае)?

Конкретно какое имя?

В комментах ответили, что имя функции объясняет что должно возвращаться (например "GetID"), но вот ведь есть printf и ему подобные. Да, программист должен бы читать документацию, но ведь гораздо эффективнее видеть имя возвращаемого прямо в IDE, как сейчас происходит со всем остальным. Видишь "возвращает код ошибки" и идёшь читать доки. Или же коды описаны прямо в комментах в коде у функции.

Что должна возвращать функция? Интересный вопрос! Есть функции, которые возвращают что-то конкретное. Вот у Вас в примере возвращается ID. Но можно договориться о том, что все функции возвращают объект определённого класса, а в этот объект можно будет уже всё что угодно запаковать.

Добавить в компилятор переключатели:

1) динамическая -> слабая статическая -> сильная статическая типизации;

2) процедурное программирование (под одного пользователя) -> ООП -> структурное программирование (где функции отдельно, а состояния отдельно).

3) еще парочку переключателей для вкл/выкл полезных, но опасных функций языка.

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

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

Согласен, что надо разрабатывать язык более высокого уровня. Но насчёт отладки не согласен, т.к. навороченные сенсоры всё равно надо будет ставить на электродвигатели. Поломка в любом сложном устройстве требует отладку, разве что ИИ что-нибудь принесёт, избавив нас от этого.

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

странно, что у функций нет имени возвращаемого значения

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

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

Но ведь то же самое делали проггеры велосипедя векторы в Си, потом всё то, что добавляется сейчас в С++. Всё это было "непонятными претензиями", а потом стало частью языка. resize_to_range выглядит такой же фундаментальной вещью, как erase, но почему-то отсутствует. Рано или поздно появится.

Приведите пример где этот метод был бы уместен? Я в своей практике такой необходимости не встречал

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

я думаю вы на удаление (это O(n) дня вектора) тратите значительно больше, чем выигрываете на бинарном поиске.

Не знаю всего контекста, но возможно вам для поиска достаточно просто принимать range или два итератора.

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

Но суть-то в том, что resize_to_range и erаse одинаковы по производительности.

Проверять все элементы подряд по одному слишком долго

В моём случае производительность не важна

определитесь уж важна или нет.

Я думаю что resize_to_range не нужен не из-за производительности, а просто потому что не вижу контекста где он был бы уместен для вектора. Поэтому и попросил пример, который меня не убедил)

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

А про resize_to_range я написал вам ошибочно, это ответ другому.

сворачивания строк/блоков кода с заголовком

Оказывается, в C# есть #region и #endregion, делающее именно это, т.е. свёрнутое даже можно подписать. И даже в VS2022 для С++ есть #pragma region, но почему-то нет в настройках постоянное сворачивание.

В плагинах для вс постоянное сворачивание предусмотрено, я делал такое для ассемблера, дополнительно к подсветке синтаксиса.

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

Одному мне кажется странным такой дискус о языке, без упоминания возможной его области применения в какой то неконкретной теме программирования? Или речь идет о программировании не ради конечной цели, а ради самого процесса, если так то это как гонять палками круги по воде. Глядишь разговор был бы более предметный.

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

Да! Конечно! Автоматное программирование! Надо обязательно поговорить о нём.

А, ведь, используют же! (Простите здесь должна была быть какая-нибудь ссылка...)

Зарегистрируйтесь на Хабре, чтобы оставить комментарий