Как мои проблемы с памятью привели к созданию синтаксиса, который невозможно забыть

в 21:00, , рубрики: Программирование, синтаксис
Около 10 лет назад у меня начались серьёзные проблемы в ментальной сфере, в том числе с памятью {впрочем, в этом есть и свои плюсы: например негативные эмоции [злость на кого-то, раздражение, обида] забываются так быстро, что практически полностью перестали меня беспокоить}. Я просто физически перестал понимать всякие сложные штуки вроде графических API или каких-то объёмных библиотек, а при выполнении рабочих задач столкнулся с такой проблемой что к концу прочтения текста какой-нибудь не самой короткой задачи я забывал начало этой задачи (так что мне приходилось перечитывать условие задачи много раз чтобы хоть как-то запомнить его).

Несмотря на то, что к этому моменту я уже закончил разработку графического движка для одного [впрочем не слишком коммерчески успешного] игрового проекта, на меня накатывала апатия и депрессия, и не удивительно — что толку быть разработчиком движка, код которого ты просто перестал понимать (а о возможностях его [графического движка] совершенствования и говорить нечего).

Вскоре так получилось, что компания Katauri, в которой я работал, фактически прекратила свою деятельность и я уволился. В результате, я совсем перестал программировать, что вгоняло в депрессию ещё сильнее. Более 2-х лет я вообще не работал и не искал работу (обстоятельства так сложились, что я жил далеко от всех своих родственников и у меня была достаточная финансовая подушка [лет на 5], что позволяло скрывать от всех своё положение), пока в начале 2016 не случилось событие [смерть моего отца], которое резко изменило мою отшельническую жизнь — я прилетел домой на похороны, и вскоре решился сказать родственникам, что я не работаю с 2014 года.

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

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

Syntaxation • Douglas Crockford • GOTO 2013:

Syntax is the least important aspect of programming language design.

Я подозреваю, это от того, что обычным программистам не составляет труда просто запомнить "как надо" и всё. А мне — составляет [причём порой очень большого труда]. Поэтому при разработке синтаксиса я вынужден был опираться не на память, а на логику. Так, практически все элементы синтаксиса нового языка имеют/получили рациональное обоснование их выбора. Остаток данной статьи я посвящу перечислению наиболее значимых обоснований выбора элементов синтаксиса, которые [эти обоснования] не встречаются в других статьях (таких как «Разработка когнитивно-эргономического синтаксиса для нового аппаратно-ориентированного языка программирования») и в документации к языку. [Про сам язык можно прочитать на его странице в Википедии. Примеры кода и документация представлены на веб-сайте языка.]

Почему аргументы функций по умолчанию константны, а переменные — нет, разве это не приводит к несогласованности, упомянутой в документации языка программирования D?

Ну переменные на то и переменные, что могут изменяться, а аргументы — это другое слово. Но самое главное почему допустима такая "несогласованность" — если при объявлении переменной абсолютно ясно что означает её изменяемость, то в случае аргументов функции такой ясности уже нет: возможно, что меняться будет копия переменной [передача по значению], а возможно, что меняться будет сама переменная, переданная в функцию [передача по ссылке]. Поэтому в 11l используются квалификаторы: = для копирования значения, & для передачи по ссылке, а в случае отсутствия квалификатора аргумент передаётся по константной ссылке (либо по константному значению, если размер аргумента не превышает размера указателя [например если аргумент целочисленного типа {т.к. использовать [константную] ссылку в данном случае менее эффективно}]).

Почему глобальные функции и типы не требуют префикса :, а глобальные переменные требуют?

Потому что глобальные функции и типы — это нормально, а глобальные переменные — это не очень хорошо.

Почему a.len/sum(a)/a.map(f), а не len(a)/a.sum()/map(a, f)?

В 11l используется кратчайшая запись:

a.len
len(a)
a.len()

sum(a)
a.sum()

a.map(f)
map(a, f)

И кроме того, функции вроде sum() (any(), all(), product(), min(), max()) всегда финальны [в отличие от map() и filter()].

Почему print() в 11l не поддерживает запятую для вывода нескольких переменных как в Python?

В Python запятая полезна для вывода нестроковых переменных:

print(a, b)

Альтернативные записи (print(str(a) + ' ' + str(b)) или print(f'{a} {b}')) более многословны.
Но в 11l можно писать так:

print(a‘ ’b)

И к тому же, в языках программирования нет консенсуса по символу разделителю — в некоторых языках (например Python, Swift, JavaScript (console.log())) используется пробел [по умолчанию], в других ({PHP (echo), Ruby, Go (fmt.Print), Pascal (write), D (write), Perl, Julia, Nim (echo)}) — пустая строка, а в Lua и Basic вообще используется табуляция {а точнее в Basic используется print zone из 14 или 16 пробелов, и пробел или пустая строка при использовании разделителя ;}.

Почему запись x, y = i, j не поддерживается (и необходимо писать (x, y) = (i, j))?

Потому что её можно спутать с записью int x, y = i, j; в Си [и её аналогом Int x, y = i, j в 11l], которая обозначает совсем другое.
[В Python запись (x, y) = (i, j) также корректна.]

Почему return a, b не поддерживается (и необходимо писать return (a, b))?

return a, b у меня ассоциируется с возвратом функцией множества значений, хотя в Python это не так — реально возвращается кортеж (одно значение типа tuple), в чём можно убедиться через print(type(f())). (Что я имею в виду под возвратом множества значений: ну, например, если функция bar() возвращает 1, 2, то вызов foo(bar()) означает foo(1, 2) [так это работает например в языке Lua], а если возвращает (1, 2), то означает foo((1, 2)).)

Почему write_bytes(), а не просто перегруженная write()?

Для симметрии с read_bytes().

А почему read_bytes()?

Сделать как в Python {то есть, чтобы в зависимости от режима открытия файла (b или t) менялся тип возвращаемого значения функции read()} в 11l не получится из-за статической типизации.

Почему null, а не none или nil?

Потому что есть nullable-типы, а не noneable.

А нельзя было обойтись без префикса @?

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

Почему для while-циклов используется ключевое слово loop, а не for как например в Go?

Для цикла while (while loop) логичным является либо while, либо loop, но никак не for.
[А в Go, видимо, сделано по аналогии с Си с его универсальным for (for (;;) для бесконечного цикла и for (;condition;) как синоним while (condition)).]

Автор:
alextretyak

Источник


* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js