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

Необычная концепция синтаксиса языка программирования

Время на прочтение8 мин
Количество просмотров8.6K
Всего голосов 10: ↑6 и ↓4+2
Комментарии42

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

НЛО прилетело и опубликовало эту надпись здесь
Большинство языков похожи друг на друга.
только не перл :-) Он принципиально отличается от других тем, что сделан «как бы я, программист, хотел, чтобы было устроено». Ровно потому тем, кто его освоил, он чрезвычайно нравится и чрезвычайно удобен — и потому же число освоивших его никогда не было большим и со временем только убывает. «Настоящих буйных мало — вот и нету вожаков».

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

brother(X,Y):- parent(Z,X),parent(Z,Y),male(X),male(Y),X\=Y
это prolog

«Компилятор языка реализуется как transpiler — преобразование исходного кода программы, написанной на одном языке программирования, в эквивалентный исходный код на другом языке.» Это уже делается в языка РФокс (Русский Фокс) www.youtube.com/watch?v=kDy4iPCFXgE&list=PLo4sldcUomOrKAPb_0A5Kv-nILQG3I7Dd&index=50
Да, эта технология очень сильно упрощает разработку языка программирования и в том или ином виде используется во многих языках.
Сначала упрощает, а потом может усложнить по мере развития. Я вижу следующую перспективу данного направления: У меня в языке Русский Фокс вы пишете программу на 1С-подобном языке программирования, но в любом месте кода можете делать вставки на FoxPro9. Получается, что РФокс наследует все возможности FoxPro9, но при этом их расширяет и делает код более читабельным, русскоязычным с доп.библиотеками. Как промежуточный файл у меня генерируется PRG-файл (FoxPro9). При этом есть возможность писать библиотеки для РФокс на языках C++, C#, Перфолента.NET, VB, Rust. В будущем я мечтаю подобную технологию применить для языка Rust (руссифицировать его), так как данный язык весьма сложен для начинающих, но весьма перспективен за счет своей безопасности создаваемого кода и выявления ошибок на стадии компиляции. Почему бы вам так же не ориентироваться на русскоязычный синтаксис?
Про русскоязычный синтаксис, точнее про Интернациональное программирование на естественных языках я уже думал, только это ни к чем хорошему не ведет. Так как это автоматически сужает потенциальную аудиторию пользователей только одним регионом (страной).
В этом отношении, английский синтаксис имеет более лучшие перспективы. Тем более даже в 1С имеются английские аналоги ключевых слов.
Но есть другой вариант: создаете файл с наборами для русскоязычного варианта и для англоязычного, потенциально можно для любого языка создавать. Потенциальная аудитория больше зависит от возможностей языка, учебников к нему, обучающих видео. Потенциальные пользователи такого языка — это начинающие программисты, если ваш язык будет простым для обучения. Профессионалы будут ориентироваться на общепринятые языки по причинам. которые можно обсудить отдельно.
Да, такая возможность есть. Более того, подобная локализация соответствует концепции DSL, которую так же можно реализовать с предложенным подходом.
Насколько я понял, все возможности императивной части сводятся к объявлению C++ функций, причём без типизации. В этом смысле я не очень понимаю, как вы собираетесь предоставить «все возможности языка реализации». Более того, какой смысл объявлять новые функции в рамках предложенного языка? Не проще определять их уже в рамках самого C++? Всё равно ведь выходит, что для программирования на предложенном языке человеку нужно уже знать C++.
Декларативная же часть в общем повторяет возможности Пролога. Почему просто не реализовать библиотеку классов С++ реализующую синтаксис близкий к синтаксису Пролога через операции? Код мог бы выглядеть, скажем, так:
Symbol tom, tim, jake, janna, parent, male, female;
male(tom) <<= true;
male(tim) <<= true;
male(jake) <<= true;
female(janna) <<= true;
parent(tom, jake) <<= true;
parent(janna, jake) <<= true;
parent(tom, tim) <<= true;

Symbol brother;
Variable X, Y, Z;
brother(X, Y) <<= parent(Z, X) & parent(Z, Y) & male(X) & male(Y) & X != Y;

brother(X, Y)[0];
brother(X, Y)();

В последних двух строках предполагается запрос первого и всех решений соответственно. В отличие от предложенного вами языка, такой подход не требует значительных усилий по реализации — по сути транслятор сведён к нулю. При этом в программах с использованием такого подхода можно будет сочетать программирование на C++ и логическое программирование. Использование уже существующих библиотек C++ и их интеграция в такую модель логического программирования также упростится.
Это всё я к чему… А нужен ли вам новый язык?
Насколько я понял, все возможности императивной части сводятся к объявлению C++ функций, причём без типизации.
Нет, не так. В императивной части можно писать какие угодно функции (для этого существую вставки кода на языке реализации). Вот только и вызывать их можно будет тоже только там.
Более того, какой смысл объявлять новые функции в рамках предложенного языка?
Без типизации объявляются те функции, вызов которых возможен из декларативной части.
Реализация языка может быть произвольной (хоть на С++, хоть на Python), а декларативная часть будет унифицирована между любыми реализациями.
Декларативная же часть в общем повторяет возможности Пролога.
Нет, возможности языка гораздо шире, чем возможности Пролога и позволяют решить основную проблему логических языков программирования, просто сейчас я на этом не заострял внимание. И основная фишка языка именно в этом, а не в его синтаксисе.

И как раз для этого и требуется определение функций и создание именно нового языка, а не просто надстройка над одним из существующих языков программирования.
Спасибо за ответ. Насколько я понял, в императивной части можно писать на языке реализации, но есть возможность объявлять функции без типизации, как в примере, которые уже и можно использовать в декларативной части. Будет ли при этом возможность совмещать императивные функции из разных реализаций? Если нет, то я вновь спрошу — зачем придумывать особый синтаксис императивной части, учитывая, что он сводится к объявлению функций? Не проще ли модифицировать сам транслятор плагинами или иными техниками прямо на языке реализации? Ведь так это делают почти со всеми скриптовыми языками, будь то Lua или Tcl — где программист может добавлять функции со стороны реализации на языке реализации, не имея потребности заучивать новый, особый синтаксис. Замечу, что и Пролог тоже можно так расширять.

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

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

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

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

Другими словами, чистые функции из декларативной части языка допускают горизонтальное масштабирование и замену прямого вычисления на вычисление с использованием нейросети.
Что имеется в виду под заменой прямого вычисления на вычисление с использованием нейросети?
В данном случае под «прямым вычислением» имеется ввиду алгоритмические вычисления на CPU в той последовательности, который задан в теле самой функции.

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

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

Исходя из этого спрошу более того: а не подменяется ли при этом сама задача? Там где от оригинала требовалось решить задачу корректно, в вашей модели решение будет получаться с некоторой вероятностью. Поэтому и проблема комбинаторного взрыва остаётся нерешённой. Вы считаете иначе?
т.е. вы предлагаете ускорить логическое программирование с использованием нейросетей?
Да, причем с помощью инструмента, допускающим автоматизацию данного процесса.

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

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

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

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

1. Синтаксис описания данных все равно необходимо формализовывать. И это приходится делать или с помощью текстового описания и последующего парсинга или непосредственный кодинг. Если парсинг — то это уже сам по себе будет определенный синтаксис некого ограниченного языка. А если кодинг — получаем запредельная сложность ручной работы, т.е. то состояние, которое имеем сейчас.

2. Для использования библиотеки требуется знание языка программирования. И не начальные, а глубокие и специфические. Причем решение с помощью алгоритмических методов или с применением нейросетей имеют принципиально разные подходы и требуются совершено разной квалификации от разработчика.
По первому пункту, простите, а вы рассматриваете только библиотеку для реализации языка? Я писал о реализации в библиотеке модели вычислений вашего языка. При этом я согласен, что если парсить язык, то это делается или полуавтоматически из текстового описания синтаксиса, или полностью руками. Если же вы говорили о том, откуда получать синтаксическое древо программы на вашем языке, то я предложил способ, отличный как от разбора текста программы, так и от задания дерева непосредственно через функции (насколько понимаю сейчас именно так). Напомню, что я предложил моделировать синтаксис языка через операции классов — где операции языка тривиально отображаются в них. Или это также запредельно сложно?

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

И никакой новый язык вам не нужен, если вы и так можете запрограммировать, например, TensorFlow на С++ или в Python, ведь транслятор и будет делать ровно тоже самое — генерировать код на С++ для вызовов функций этих библиотек.

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

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

Новые языки именно потому и нужны, что они позволяют проще программировать в рамках некоторой модели, позволяют думать о программе по-другому. Каждый язык поощеряет некоторые модели — так Хаскель об одном, Си о другом, Лисп о третьем, Пролог ещё об одном, Verilog и VHDL — вообще из другой оперы немного. Имея библиотеку в рамках которой вы можете проводить вычисления по своей модели уже проще создавать наиболее подходящий язык. Я описал путь возможной реализации такой библиотеки, который может упростить последующую разработку.

В любом случае удачи в этом проекте — жду следующей статьи, где, надеюсь, будет продемонстрирована работа программ такого стиля. =)
PS: а есть ли репозиторий с текущим кодом?
Есть конечно. И библиотека есть (трансплайтер реализуется как несколько вызовов из этой библиотеки). Просто сейчас я не ориентируюсь на чистоту кода и правильность архитектуры, а пишу как удобнее. Рефакторинг будет после реализации, и подозреваю, что это потребуется сделать не один раз.
А репа сейчас закрыта от публичного доступа. Открою сразу, как заработают хотя бы пара примеров.

И спасибо!
Всё равно ведь выходит, что для программирования на предложенном языке человеку нужно уже знать C++.
Это требуется только в том случае, если разработчик будет писать в императивном стиле. И кстати, это наверно самая большая проблема, за которую критикуют Пролог.
Т.е. при написании в чисто императивном стиле необходимость в вашем языке полностью отпадает. А иначе императивная часть сводится к расширению декларативной — тогда смотрите комментарий выше.
Да, при написании только в императивном стиле существуют более удобные и распространенные инструменты.
отсутствует проблема, присущая практически всем промышленным языкам — постоянное увеличение сложности синтаксиса языка из-за его естественного развития

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

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

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

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

И что же нам может дать очередной язык программирования в свете показанной выше картины? Как он снизит трудозатраты?

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

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

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

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

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

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


Первое. Транспиляция в C (не в C++) может быть более гибким решением, когда вы будете добавлять понятие объекта. Семантика управления жизни объектов С++ — довольно специфическая, привязка к ней, с одной стороны, ограничит выбор возможностей, а, с другой стороны, повлияет на уровень сложности не в лучшую сторону. В качестве примера языка, старающегося избегать эти проблемы, приведу Nim. Его флагманский бэкенд — C (C++ бэкенд есть, но он альтернативен и, вероятно, не поддерживает недавно добавленные возможности Nim). В C++ деструктурирование объекта, даже уже перемещённого куда-либо, обязательно — поэтому перемещающие конструкторы, операторы присваивания должны заботиться об "опустошении" перемещённого объекта, чтобы при выполнении деструктора ничего не происходило. Такое (необязательное, если проектировать язык с ноля) усложнение специфично для C++, поскольку move-семантики не было в начальной версии языка, а когда она была введена позже, её нужно было "гладко" примирить с предшествовавшими правилами (диктующими обязательность вызова деструктора). В Nim, насколько я понимаю, эта лишняя сложность преодолевается: деструктор — лишь один из способов уничтожить объект, одна из потенциально нескольких "поглощающих" объект функций (хотя и наиболее стандартная и частоупотребляемая). Не знаю, как авторы Nim примеряют это c правилами C++ в C++-бэкенде языка (если оный не заброшен). Также, транспиляция в C кардинально упрощает проблемы FFI, бинарной совместимости раздельно скомпилированных библиотек. У C++ с этим — большие проблемы. Любопытное стороннее ответвление темы про объекты — в языке R более одной "системы объектов", запрограммированной поверх ядра языка в виде библиотеке.


Второе. В ваших примерах вы объединяете последовательное выполнение ("императивное") с бэктрекингом в духе Пролога ("декларативное" — под которым, на самом деле, в Прологе подразумевается более сложное императивное исполнение — с бэктрекингом; в частности, в Прологе порядок выражений, перечисленных в правой части через запятую, играет важную роль в плане производительности и вообще завершаемости исполнения "декларативной" программы). Обратите внимание на концепцию алгебраических эффектов (хорошо развитый пример — Koka, который, кстати, в новой версии тоже транспилируется в C), объединяющую под одим зонтом не только эти два аспекта, но и эффекты другого рода — исключения, завершаемость, асинхронность, недетерминизм, сторонние эффекты (state), асинхронное исполнение… (язык позволяет программировать новые эффекты кроме определённых в базовой библиотеке). У Koka — солидный математический фундамент: система алгебраических эффектов обладает свойствами, похожими на комбинирование монад в Haskell, при более компактных "церемониях", ложащихся на плечи программиста, использующего язык. Кстати, ещё один интересный аспект Koka — минималистический синтаксис, например, синтаксис while { тут условие } { тут действие } — это не встроенная конструкция языка с ключевым словом while, а вызов функции while, принимающий два параметра — анонимные функции. В Nim есть похожие синтаксические идеи, но Koka — более изящен в этом плане.


Третье — система гигиенических макросов может обеспечить минимальность ядра и богатый, знакомый "программистам на языке ..." синтаксис запрограммированный в базовой библиотеке поверх макросов. На ум приходит Racket (потомок Scheme, язык с богатыми средствами построения DSL) — к сожалению, для использования Racket нужно погрузиться в его лиспоподобный мир. С другой стороны, система гигиенических макросов регулярно появляется в современных языках (примеры: Nim, Rust, Julia) — это хороший способ сохранять ядро языка компактным, а богатство (выразительность) синтаксиса выносить в библиотеки.

Большое спасибо за развернутый комментарий и ссылки на примеры языков. Самое интересное, что некоторые их идеи я заимствовал (или попробовал это сделать).
Транспиляция в C (не в C++) может быть более гибким решением, когда вы будете добавлять понятие объекта...
Решение действительно будет более гибким, но значительно возрастает трудоемкость реализации трансплайтера. Для реализации на С++ достаточно переопределить операции и генерируемый код уже можно компилировать.

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

И по факту сейчас многие библиотеки и проекты используют именно С++ модель, а не чистый С (llvm, tensowflow), а они первые кандидаты на дальнейшее использование.

Кажется я отвечал, что пример на Прологе я взял просто как самый известный язык логического программирования. Но модели выполнения и их реализации у меня и в Прологе различаются принципиально.

Согласен с аргументом в пользу C++ бэкенда (про использование конкретных удобств, перегрузки операторов в вашем случае). Меня беспокоит нетривиальная модель жизненного цикла объектов в C++ — в случае, если C++ бэкенд на неё закладывается, она может протечь в семантику разрабатываемого языка, привнося риск искусственного усложнения. Если в генерируемый C++ коде не опирается на автоматический вызов деструкторов, жизнь проще… Однако, если, например, поддаться соблазну использовать хотя бы unique_ptr, вещи усложнятся.


В сторону от темы — вспомнил про появившийся на рубеже тысячелетий прологоподобный язык программирования Mercury, годами не вспоминал про него, а он, оказывается, жив! Ну, жив настолько, насколько бывает жив академический язык. Почитаю официальный сайт на досуге (меня интересует система типов в первую очередь).

Да, про Mercury тоже знаю.

А что касается С++, то я ориентируюсь в реализации сразу на С++11 и выше с контролем времени жизни объектов и другими вкусностями, которые значительно упрощают работу, в том числе и управление памятью.

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

То есть бинарный предикат представляется как пара объект/словарь.
А как планируется представлять предикаты большей арности?

Немного не понял вопроса. В чем сложность?

В текущем представлении все возможные комбинации описаны в одном месте. Если связь один — к одному, то это представлено в виде множества объектов (словаря) с правой стороны.


Но если арность выше, то что справа — словарь словарей? Для всех возможных комбинаций?

Наверно я еще не проснулся ;-(
Речь идет о свойставах объекта или о значениях свойств?

Если о свойствах объектов, то это одномерный словарь, у которого имена элементов обязательны.

Если о значениях свойств, то значением может быть в том числе и словарь у которого значением элемента так же можно быть словарь, т.е. размерность и вложенность не ограничена.

Вопрос был о втором. О значениях свойств.


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


Более того, не очевидны преимущества перед представлением подобного в императивном стиле. Т.е. в виде метода или свойства, возвращающего словарь.


То есть вся "магия" — в преобразовании (транспиляции) декларативной функции в специфическом синтаксисе — в обычную, выполняющую перебор?

Все, я кажется понял! Большущее спасибо за поднятую тему!
И это очень важный момент, т.к. вы правильно заметили, данные в моем примере и факты в примере на Прологе записываются противоположным образом. На Прологе, как набор фактов, которые связываю разные объекты, а в моем случае, как набор свойств у одного объекта.

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

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

Что же касается «магии», то Пролог вынужденно использует именно такое представление, т.к. это требуется для его внутренних механизмов неявного поиска решения. Ведь он оперирует именно «фактами».

В моем случае все совсем по другому и механика поиска возможных вариантов явно задается с помощью итератора. А сам перебор реализуется за счет перебора значений объекта, которые и представлены итератором.
Я думаю, что Python обладает достаточно низким порогом вхождения, и не обладает умопомрачающей сложностью, в целом, в этом ключе вот этот язык как мне кажется, будет невообразмо сложнее, так как сложность языка будет равна когнитивной сложности базового языка + когнитивной сложности языка транспиляции. На примере метрик, применяемых к оценке сложности программного кода, ваш код предназанчемый для транспиляции, будет на порядок сложнее, чем просто код на целевом языке транспиляции
Если оценивать сложность обеих частей языка, то естественно это будет сложнее, вот только делать этого ненужно, т.к. назначение у этих частей разное и оно не пересекается. Ведь каждый инструмент нужно использовать только для тех целей, для которых он предназначен. Иначе очень легко нарваться на антипаттерн "золотой молоток"

Если алгоритм решения задачи известен и достаточно императивной семантики, то данный язык использовать ненужно и проще взять тот же Python или С++.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий