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

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

Очередной паскаль?


Скажите, а как в вашем языке описывается передача замыканий в функцию? Или вы не планируете замыканий?

1. Лучше, с учетом того, что стоять на плечах гигантов, изучая их опыт конечно удобнее. Pascal для начала 1970-х был хорош для программирования разнообразных задач, несмотря на небольшие недоработки в синтаксисе.

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

А на чьих плечах вы стоите? Т.е. какие языки вы используете как основу? Scala, F#, ocaml, haskell, rust, C++17?

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

Далее при конструирования синтаксиса для каждого элемента, начиная с комментариев исследовалось, как это сделано в других языках и почему. В этом очень помогает книга: Programming Language Pragmatics (если кто её не знает и интересуется темой языков, то рекомендую). Трудно выделить какой то один язык, но похоже, что по базовым элементам более Swift, так как текущая версия интерпретатора написана на нем и первое приложение будет для AppStore.

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

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

Мне лично тоже это было непривычно, но после двух — трех десятков текстов в итоге стало даже нравится.
предпочитают строчные буквы для ключевых слов

А многие ещё и не видят в них разницы, так как буква «A» и есть буква «a», как её ни запиши — в строчном или прописном виде, рубленым, курсивом или готическим начертанием.


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


зарезервировать таким образом все ключевые слова, чтобы при расширении языка в будущем идентификаторы разработчика не попали в будущие ключевые слова

Постоянное расширение языка — это плохая идея: язык должен быть стабилен.


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


Мне лично тоже это было непривычно, но после двух — трех десятков текстов в итоге стало даже нравится.

Ну, тут вы немного лукавите и недоговариваете:


Кроме того текст тестовых фрагментов программ с AND, OR и NOT выглядел слегка тяжеловесно.

— Ваши слова.

Ладно, давайте сыграем в эту игру, но только разок, хорошо?
В начале, обратите внимание на прошедшее время глагола "выглядел" второй цитаты по отношению к "тестовым фрагментам". Затем снова прочтите вторую часть первой цитаты: "после двух — трех десятков текстов в итоге стало даже нравится". Возможно потребуется еще спросить себя, а зачем были нужны «два — три десятка текстов» на пока еще не существующем языке?
Есть ли более разумные объяснения «лукавству»?

Если вам нравятся цитаты, то рекомендую ознакомиться с той действительно хорошей, что я привел еще в начале первой статьи.
" вы создали большую проблему для слабовидящих и слепых."
Это важное предположение, но непонятно почему вы так считаете, можете пояснить суть проблемы для слабовидящих?
А многие ещё и не видят в них разницы, так как буква «A» и есть буква «a», как её ни запиши — в строчном или прописном виде, рубленым, курсивом или готическим начертанием.

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


Потому с Pascal им просто работать, с Си — хуже и ASN.1 — ещё хуже. (В последнем тип лексемы зависит от регистра первой буквы слова.)


Это не абстрактные умозаключения, а опыт общения со слепым промышленным программистом.

Спасибо, изучим эту тему детальнее

У BOOL нет xor'a?

А зачем давать новое имя операции, которая уже есть? Операция сравнения на неравенство же и есть исключающее или для булевых выражений: a ~= b.


| a | b | a ≠ b |
| 0 | 0 |   0   |
| 1 | 0 |   1   |
| 0 | 1 |   1   |
| 1 | 1 |   0   |

Резонно. А для целых битовые операции есть?

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

Операторы для обозначения битовых операций над целыми числами не планируются. По этой причине для операций с типом BOOL использованы обозначения & и |, а не && и ||.

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


Если бы было более строгое разделение типов, как, например, в Pascal, то и не было бы никакой причины вводить отдельные операторы. Пример тому можно найти в реализации Free Pascal:



(Free Pascal данный синтаксис, если не ошибаюсь, поизаимствовал у Borland Pascal.)


Так что никакого смысла в «странных» && и || в вашем случае нет, даже если бы и планировалось.


P.S. Ну а если вы ратуете за легкость восприятия («с возможностью легкого прочтения»), то непонятно, зачем вы взяли &, |, ~, ~= вместо and, or, not и <> как это, например, в Pascal, при разработке которого, полагаю, Вирт вот по этой же самой причине отказался от алголовских \/ и /\, которые понятны математикам, но новы для прочих.


P.P.S. Интересный факт: сам по себе символ обратной косой черты появился именно для записи логических операторов Алгола в виде диграфов: «\» + «/» и «/» + «\».

Интересная информация, особенно про /\ \/ в Algol, спасибо

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

addOperator = "+" | "-" | OR.
mulOperator = "*" | "/" | DIV | MOD | AND.
relation = "==" | "<>" | "<" | "<=" | ">" | ">=".

Но здесь возникает вопрос, на который нет логичного ответа: почему для одних операторов мы используем знаки, а для других сочетания букв [английского языка]? Заменять “==” на что-то вроде EQUAL, а “*” на MULT, кажется неуместным. Кроме того текст тестовых фрагментов программ с AND, OR и NOT выглядел слегка тяжеловесно. Ну и сканнер интерпретатора распознает токены как сочетания букв немного дольше символов знаков.

Символ & вполне употребляется в значении “and”. Вирт его кстати использует в Oberon. “|” не столь очевиден, но благодаря синтаксису С почти всем знаком и вписывается вполне органично. У нас есть задумка позднее полноценно использовать символ “!” ближе к его исходному значению, not выражается знаком “~” (Oberon), отсюда следует вполне логичное “~=” (Lua, Smalltalk) вместо “!=” и “<>”.

Автор “<>” вероятно имел в ввиду прочтение “или < или >”, что логично для comparable величин, но “не равно” может применяться и для других величин несравнимых по принципу больше — меньше.

Присваивание “:=” логично с абстрактной точки зрения, но менее эргономично чем “=”, к тому же все пишут рукой арифметические выражения “=”.

Не очевидно использование “~” как not. В математике вроде в этом качестве он не используется. Интересно откуда он проник в ряд языков?
Но здесь возникает вопрос, на который нет логичного ответа: почему для одних операторов мы используем знаки, а для других сочетания букв [английского языка]?

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


Заменять “==” на что-то вроде EQUAL

А не надо заменять знак равенства ни на страшное «==», ни на слово, тем более, прописными буквами. Операция «==» — это вообще что? Почему оно вот так записано?


Кроме того текст тестовых фрагментов программ с AND, OR и NOT выглядел слегка тяжеловесно.

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


Вы знаете, почему в ранних языках программирования писали часто прописными буквами? А почему многие из ранних не чувствительны к регистру? Ответ банален: цена ПЗУ знакогенератора с поддержкой строчных букв была в два раза выше: целый 1K для ASCII 8×8 (а для приличного вида строчных нужно матрицу увеличить раза в два).


Времена изменились, данного ограничения уже нет. Нет ограничения — нет причины кричать. (Только не нужно сразу приводить в качестве контраргумента нишевые и полумёртвые языки: лучше сначала поразмышлять, почему они нишевые и полумёртвые.)


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

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


Не нужно заниматься ранней оптимизацией.


Символ & вполне употребляется в значении “and”.

Данный символ — это лигатура латинского et, которое и есть союз «и». И для британцев, например, нет проблемы прочитать этот символ как-то иначе: в языке огромное число заимствований из латыни и в знаке лигатуры ясно видно две буквы «e» и «t». Американцам хуже: они ради скорописи упростили лигатуру до «восьмёрки с хвостиками».


Вот только в литературном письме данный символ используется только в названиях. Он даже не используется (в литературном письме) в иных заимствованиях из латыни, где этот союз часть фразы. (Потому многие здесь не поймут &c, применяемое в мессенджерах в английском.)


благодаря синтаксису С почти всем знаком

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


Синтаксис языка C — это расширенный синтаксис языка B, котрый, в свою очередь, лабораторный язык, написанный математиками для математиков. (Кен Томпсон, разработчик B, хорошо известен с 60-х своими работами по регулярным грамматикам (выражениям) и преобразованиям конечных автоматов.)


Математикам привычно вводить новые обозначения для сокращения записи (периодически они слишком усердствуют в этом). А тут ещё и необходимость: программы вводились через терминал, представляющий из себя принтер с клавиатурой, объединённые модемом (на фото по ссылке, вот, сам Кен за терминалом).


Вы пробовали поработать с редактором ed? Строковым редактором. Для полноты ощущений нужно отключить редактирование вводимой строки и использовать для удаления предыдущего символа один из видимых «лишних» символов. (Если не ошибаюсь, это был октоторп.)


Вот потому в C и столько коротких лексем для конструкций языка. Математики для математиков в стеснённых условиях. Позже, для пользователей они написали компилятор FORTRAN.


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


Не очевидно использование “~” как not. В математике вроде в этом качестве он не используется. Интересно откуда он проник в ряд языков?

Математики используют «¬» или, в некоторых школах, черту сверху для обозначения инверсии. А тильду стали использовать, потому что ASCII. Тильда «лишний» несамостоятельный символ, а символа «not» в ASCII нет. (Тильда — это знак акцента, он для печати сверху буквы — самостоятельно не применялся.)


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


Автор “<>” вероятно имел в ввиду прочтение “или < или >”, что логично для comparable величин, но “не равно” может применяться и для других величин несравнимых по принципу больше — меньше.

В Pascal всё, что можно сравнивать строго упорядочено, потому, да, можно применять «больше/меньше» как эквивалент неравенства. Если вам нужно сравнивать неупорядоченные величины, то можно использовать диграф «/=», как замену «≠», как и реализовано в некоторых языках.


Да, автор — это Никлаус Вирт и он в Oberon уже использует октоторп для обозначения оператора сравнения на неравенство. (По-моему, это ужасно выглядит.)


Присваивание “:=” логично с абстрактной точки зрения, но менее эргономично чем “=”“=”.

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


к тому же все пишут рукой арифметические выражения

Не-не-не, все пишут равенства. Равенства либо как утверждения, либо как условие. Операция присваивания не является ни первым, ни вторым.

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

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

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


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

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


Постоянное расширение языка — это плохая идея: язык должен быть стабилен.

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


При этом я не против расширений вообще:


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

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


Правда, это будет уже контекстно-зависимая грамматика, но как небольшое зло это можно пережить. Например, указание кодировки в meta-теге в HTML точно такой же пример контекстной зависимости.


Реализуется просто: небольшой костылик в лексическом анализаторе и всё (новый синтаксический анализатор не увидит новых ключевых слов — он увидит идентификаторы): посмотрите на Dragon Book — там ключевые слова при лексическом разборе отличаются от идентификаторов по флагу/полю в таблице символов.


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

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


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

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

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

Вот допустим по итогам этой статьи у нас есть язык калькулятора. В следующей добавим конструкцию IF и WHILE. Ура, теперь можно программировать ветвление и циклы. Далее подпрограммы. Теперь мы может строить программы из текста более чем высота экрана. Далее дадим инструмент связи программ друг с другом. Ура, теперь мы можем создавать более сложные системы, ориентируясь на ранее созданные части и т.д. Но если вам не нужны разнообразные возможности, то ваши решения продолжают работать по прежнему.
Вот допустим по итогам этой статьи у нас есть язык калькулятора. В следующей добавим конструкцию IF и WHILE.

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


Далее дадим инструмент связи программ друг с другом.

Далее добавим операторы управления файлами, операторы синхронизации, операторы для построения GUI, операторы передвижения в пространстве, операторы...


А Томпсон с Ритчи решили, что им не нужно расширять язык для добавления такой функциональности, достаточно определить ABI и возможность линковки объектных модулей программы, написанной на Си, с таковыми написанными на ассемблере (или любом другом языке).


И всё, интерфейс функций и C ABI ныне используется повсеместно и целой армией других языков.


чем плохо развитие языка через расширение его возможностей?

Тем, что большой и сложный язык труднее знать, читать и понимать. Почему Google использует Protobuf, созданный как свободный проект одним человеком, а не ASN.1? Не потому ли, что в грамматике последнего ныне сотни правил и с каждым новым стандартом их всё больше и больше?

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

Модель С оказалась жизнеспособна, но полагаю это не достоинства самого языка (простым, понятным и надежным при своей относительной компактности он точно не являлся), а стечение обстоятельств, включая связь с UNIX.

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

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

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

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

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

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

Публикации

Изменить настройки темы

Истории