Comments 32
Очень зубодробительные штуки вышли, конечно
Особенно то, что #$ и $# это абсолютно разные и не связанные по смыслу вещи.
Это после фразы про то, что все должно быть понятным даже новичкам)
На практике в 99% случаев нужно только $#. А пара была выбрана просто потому, что ее очень быстро набирать безо всякого автозаполнения. По практике — это оказалось очень удачным решением.
#$ не очень удачный тк реально можно перепутать, а вот с $$ можно сделать красивое ветвление, поэтому он и был введен в оборот.
Мне кажется, что вы зря начали изобретать новые смыслы и правила.
Гораздо проще попытаться приспособить уже существующие, чем придумывать новые ни на что не похожие правила и синтаксические конструкции.
Хотя в паре комментариев сложно все написать ...
Это стандарт, когда пишешь: «знаете, я тут синтаксис придумал» — миллион людей спросят «а зафига?» :) В моем случае это решало простую задачу — научить пользователя, который вообще никакого языка не знает дистанционно за 2 дня. Это получается. А так, если есть возможность отказаться от разработки DSL — надо отказаться.
Очень круто, что вам удобно решать ваши задачи на вашем языке. В конце-концов, в DSL, как мне кажется, главное — DS. Но с точки зрения мимопроходила, выглядит немного... непривычно? некрасиво? Не знаю, как сказать одним словом, поэтому попытаюсь описать по пунктам в треде.
Всегда думайте о том, как вы будете потом обучать других людей
Как мне кажется, для этой цели очень сильно поможет, если синтаксис языка будет хотя бы отдаленно напоминать другие. Многие DSL даже начинаются как библиотеки для других языков. Вашему, к сожалению, нужно прямо осознанно обучаться; многие моменты на первый взгляд не очевидны.
Удаляйте лишнее
Возможно, стоит иметь в виду какую-то "базу", из которой не стоит ничего удалять, даже если хочется. В случае языков, похожих на другие — это общие привычные элементы синтаксиса. В вашем случая — мне очень кажется, что лучше было оставить привычную математику со скобками. Это перекликается с другим пунктом: вряд ли кого-то нужно обучать арифметическим выражениям, а вот про то, что скобки в них нельзя, нужно сказать отдельно.
Я вообще не ориентировался на тех, кто что-то уже программирует. Поэтому специально не привязывался к уже-существующим синтаксисам. У меня была очень простая задача — за два-три дня дистанционно обучать людей не имевших никакого опыта программирования. И она реализуется — иначе я бы не стал писать статью.
Вообще если стремится сделать очень похоже, но не совсем в концепции приложения — лучше взять JS или Lua.
Вы не первый, кто попытался сделать ЯП, на котором бы могли программировать люди не умеющие программировать. Ещё в 50е пытались сделать это. Самые знаменитые языки, на которых, как предполагалось, сможет писать любая секретарша это Cobol и SQL. Однако пока никому не удалось сделать такой язык.
Но вы в любом случае молодец!
Лучший результат у нас — это если человек когда-то в далеком прошлом лабораторку на фортране делал :) В смысле давно, немного и криво программировал что-то и бросил. Такие пользователи прям в восторге.
Сейчас самая большая проблема для нас — это не объяснять синтаксис (с этим все совсем просто), а с объяснением хорошей архитектуры решения. В 60% случаев начинают делать так, как у них было в табличке эксель и соответсвенно тянут оттуда все архитектурные ограничения. Вот это быстро пофиксить не получается — делаем консультации, записываем видосы. Если пользователь не программировал никогда и ничего и разбирается со всем сам, то сейчас он со своего второго проекта начинает понимать как таблички должны быть организованы, а я хочу чтоб с первого.
Но если проект простой — до 5 табличек, то там любая архитектура прокатывает. А потом (после этих 5 первых) таблички людям мозг захватывают и их система начинает расти 5 -> 30 -> 100 -> 150 (это реально уже проект-монстр который даж меня пугает).
Пользователи не хотят кодить, это тоже нужно понимать, даёшб им конструктор кода
Добавляйте автозаполнение везде, где получится
Не забывайте про хоткеи
Постарайтесь избегать диких цветов в подсветке
Судя по этим пунктам, мне кажется, что вам не хватило в начале еще одного, возможно, более главного:
Изучите существующие инструменты для написания DSL
Подсветку синтаксиса можно сделать без указания конкретных цветов, а с указанием семантики токенов. Самое простое — грамматики TextMate, которые поддерживают из коробки, например, VS Code и Shiki.
А все эти три пункта можно решить, если постараться поддержать хотя бы некоторые фичи из Language Server Protocol. При этом у вас почти сразу появится много мощных инструментов для вашего DSL.
Комбинации лучше, чем отдельные экзотические символы
Если честно, мне не совсем понятно, почему вы решили для настолько многих случаев использовать спецсимволы, пусть даже комбинации, вместо слов или их сокращений. Возвращась к предыдущим пунктам: мне кажется, что такой подход позволит обучиться вашему DSL намного легче и быстрее.
Не совсем понимаю, например, почему =:
вам кажется лучше, чем что-то вроде start:
или main:
.
Или почему, к примеру, $#smth
— это системные переменные, а не, например, $sys.smth
?
$sys.smth есть точка и мне хотелось, что бы стартовый символ или пара отличались. Мы используем точку в паре мест, но в основной массе старались ее избегать. Когда 3-й день программируешь — точки плохо читаются.
Про start: — это очень похоже просто на определение строки, а нужно было железное отличи. В качестве развития — в кодах, где несколько последовательных блоков в одном используется с префиксом:
a1=:
a2=:
ch1=:
Нравится идея с определением переменных после. Где-то в другом языке подсмотрели?
#field_name
и получаем вместо него значение этого поля
Если значение поля field_name_A равно field_name_B, а значение поля field_name_B равно 777, то правильно ли я понимаю, что ##field_name_A = 777 или нет?
Сначала сделали это, а потом отказались, так-как было много ошибок. Пользователь копировал вызов поля вместе с диезом и вставлял поставив в начале дополнительный диез. Получалась логическая ошибка не отображаемая в подсветке — поэтому решили, что такой случай надо определять через отдельную строку:
= : #$field_name
field_name: #h_field_name_a
А чем вам не угодил, скажем, питон? Запретили бы всякую магию, оставили бы базовый синтаксис и, мне кажется, было бы намного читабельней.
Мы столкнулись с тем, что придется дофига всего позапрещать. И большая часть документации состояла бы из «это не трож», «сюда не ходи» и тп. Те надо было бы научить питону, а потом ограничениям над питоном — по мне, так это безнадега. А сейчас, если программисту надо разобраться (реально надо) то день потыкал и уже почти бог.
Да и у пайтона совсем другая логика — у нас очень много декларативщины, нам если брать, то надо было бы брать хаскель-подобные.
Ну вы бы не говорили никому что это питон :) так, похож только :) Запрещать готовое имхо проще чем делать парсер и интерпретатор самим, да и работать быстрей будет (можно использовать обычный питон интерпретатор, встроенные функции можно писать на полноценном питоне - главное никому об этом не говорить). Например, можно взять какой-то готовый линтер и понаписывать в нем правила, которые разрешают конструкции только из белого списка тех, что вам кажутся достаточно простыми.
Просто ваш код (субъективно), реально похож на питон, только нашпигованный спец символами, которые, кстати, лично у меня сильно отвлекают внимание.
мотивация понятна, но вот мне кажется есть несколько отклонений от общего
придумывать свой синтаксис, не язык, а именно синтаксис задача не очень благородная
почему - просто большинство текущих mainstream языков по синтаксису больше похожи друг на друга, в них больше общего чем разного, а раньше это было не так
например Java и C# общие:
вызовы через круглые скобки, аргументы - разделены запятыми, присваивание слева (переменная) на право (значение) через символ равно, передача значения - вызов функции - поддается той же логике: result = fun ( arg1, arg2 ) - тоже все значения текут справа на лево: сначала аргументы в функцию, из функции в результат
это уже стало на столько естественно, что как-то меньше попадается вот этого
result := fun ( arg1, arg2 )
или
procedure( arg1, arg2, result ) - тут результат засовывается в конец и вообще не понятно становиться как построить цепочку выражений, вообще в том же bash, powershell для этого сделали вертикальную черту
тенденция использовать спец символы в именах переменных в mainstream уходит, медленно уходит PHP (да простят), там например переменные начинаются с $, а с perl там еще вроде хлеще было
языки постепенно по синтаксису упрощаются и идут в сторону лаконичности, в том же C++ и PHP вызов метода через -> (obj->method(arg,arg)) (через точку то же есть, но у них семантика разная), а уже в Java и в других поздних уже точка (obj.method(arg,arg))
убираются опциональные детали, а у вас на оборот, начинаются проблемы $ $@ @$ ' " ` ``` с таким успехом не долго дойти до bash / perl - а это уже тупик будет
я бы посмотрел на более лаконичные решения, например очень сложно из нормального языка выкинуть круглые скобки - они задают порядок вычисления, а если серьезно говорить - то структуру (AST), все остальное просто, от других вещей можно избавиться, например в Scala есть массивы, но их использование не отличается особо от функций array(item) в Scala, то же что array[item] в Java, просто по смыслу, работа с функций (fn(a)) не сильно отличается от работы с массивом (arr(a)) (при условии что функция чистая) - вот в Scala и выкинули лишнее
На мой взгляд проблема изучения языка - это не синтаксис, любой синтаксис можно запомнить (дело от пары дней до пары недель), а в усвоении структуры и синтаксис в данном случае должен помогать, а не мешать, чем меньше и полнее у вас будет синтаксис тем меньше запоминать его и больше времени останется на структуры (циклы, ветвления, функции)
Когда дойдете до определения тела функций - последовательности вычислений, то лучше сразу откинуть идею со statements и перейти к expressions, и за одно циклы while выкинуть оставить только recursion и tail recursion, я бы еще if выкинул, заменил бы на pattern-match
Спасибо, что написали — у меня была возможность еще немного поразмышлять в этом направлении. Если говорить про язык, то вы все верно пишете (не просто так же языки эволюционировали).
Дело в том, что у нас не язык — к нему надо относится как к «конфигу на стероидах».
Еще важен скилл того, кто с ним работает. Когда человек больше трех лет смотрит в километры кода — он хочет, что бы там отсутствовали лишне элементы — он по виду функции знает, что третий параметр это..., последний это result, сразу хочется вложить преобразование в передачу параметра внутри функции и тп.
И я про это как-раз хотел сказать в статье — если подходит имеющийся синтаксис, то надо брать его. А если цель другая, то надо с этим бороться. Те нет задачи разработать синтаксис, ради того, что бы его разработать — это дичь.
А я же сознательно делал «инстаграм синтаксис», так-как мой пользователь — это человек, который про программирование не знает. А вот # как тег и @ как указание пользователя ему знакомы. Вот какой паттерн мы активировали.
Также он воспринимает = как знак сравнения и страдает от концепции присваивания (поэтому присваивание отправили в топку, оно есть, но почти никогда не используется). while тоже есть, но люди его использую не так как вы привыкли — а для выполнения нескольких последовательных действий :) Про рекурсию я целый абзац написал — она есть, но когда я про нее пытаюсь пользователю рассказать у него на лице написано, что он хочет поскорей пойти набухаться и забыть про это.
Это была еще одна мысль про которую сразу непонятно — иногда упростить с ограничением возможностей, если вы большой профи, очень сложно.
Например мы через 4 года только поняли, что нашим пользователям в 99% случаев while как while нужен только для того, что бы последовательно перебрать имеющийся список. Тогда мы сделали для этого функцию, которая всегда пережевывает весь список от начала до конца без возможности выхода, итератора и всего прочего, чего есть в нормальном while. И это было настоящим открытием — сложность проектов у людей сразу выросла.
Какие у нас есть клавиши в клавиатуре или как непрограммист язык разрабатывал