Эльфийский язык программирования

Как известно, если ты серьёзный программист, синтаксический сахар тебе не нужен, это баловство. Ещё несколько лет назад Python считался детской погремушкой именно из за этого. Чем вам фигурные скобки мешали? Ребячество какое-то придумали: заменить фигурные скобки на отступы табуляции. Сказал солидный дядя. Маличики согласно покивали, виновато глядя в потолок. Через год все работали в коллективах где Питон основной язык.Правильное развитие языков какое? А вот какое. Берётся паттерн программирования, который применяется в нынешнем языке, и делается попытка внедрить этот паттерн на уровне самого языка в уже новом языке. То есть жила-была функция без имени, вы её называли лямбда, может быть даже имя было, но оно было не нужно вам, просто компилятор требовал, ну называли «f1», а в новом языке это сразу — лямбда! Или был массив, вы как то ограничивали его длину и состав, и как следствие называли его кортежем, а теперь, вуаля, он у вас сразу — кортеж и удобнее пользоваться. Использовали вы отложенные расчёты сложно ухищраясь на С++, а теперь — бамс! и у вас прямо на уровне языка то же самое, называется lazy eval, только с монадами осторожнее, Люк. А что такое монады, мастер Йода? Ой всё! Подразумевается, что если ты используешь такой новый язык, то ты уже обязан ЗНАТЬ эти паттерны и уметь их применять. Повышается репутация и рыночное преимущество уже от того, что в си-ви написано название языка содержащего новую семантику ассоциирующуюся у сообщества с лучшими достижениями. С другой стороны, кто круче шарит, например, в замыканиях, тот, кто применяет их в современном языке с лямбдами или тот, кто их много лет применял на Си? Вопрос риторический.

Так что синтаксический сахар или семантическое мясо, это вопрос открытый.

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

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

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

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

Просто для примера, картинка абстрактного искусства:

this.a = this.compare ((this.b + this.c) && this.d, this.x + this.y / this.z,

(function () { var closure = 'val'; return function () { alert (closure); }; })())

И так на пол экрана! Мне ужасно захотелось, просто чтобы понять, что происходит стереть все упоминания this, примерно так:

a = compare ((b + c) && d, x + y / z

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

Тогда я решил сделать экспериментальный язык, где заменить this на ⚫, function на ➮.

⚫a = ⚫compare ((⚫b + ⚫c) && ⚫d, ⚫x + ⚫y / ⚫z,(➮() { var closure = 'val'; return ➮() { alert (closure); }; })())

Опыт транспилеров у меня уже был, с проектом dotcall, а вообще система транспиляции в JavaScript мне приглянулась в coffeeScript. Дело сразу пошло. Сделав маленький траспилер в JavaScript я стал активно пользоваться своим детищем, чтобы посмотреть, насколько это удобно на практике. Ввод необычных символов сразу меня беспокоил, ведь на клавиатуре всего 32 символа. Но использование замены по табу решило эту задачу, набирать на практике оказалось очень удобно и легко.

Поскольку я каждый день много раз вынужден набирать конструкции вроде такой:

for (var i = 0; i < data.length; i++) {

и давно мечтал иметь её сокращёный аналог, у меня даже прижилось в С++ макро each (i, array), я решил сразу сделать и такое:

i ⬌ data {

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

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

Поскольку я не пользуюсь отладчиком, а пользуюсь выводом в консоль и отладочными кодомодификациями, то есть фактически набираю console.log () десятки и сотни раз за трудовую сессию, то мне сразу захотелось упростить этот набор, и вместо:

console.log ('hello world', '!')

набирать

ロ 'hello world', '!'

Собственно предыдущая строчка это и есть hello.yy, то есть «hello world in elfu programming language»!

Потом, в функциональном программировании часто встречаются упрощённые функции, вроде того:

this.data = this.data.map (function (item) { if (item > 20) return item })

после замены function на ➮, было решено попробовать пойти дальше, гулять так гулять:

⚫data = ⚫data ⧉ (➮ item { ⌥(item > 20) $ item })

как видите: ⌥ это if, ⧉ это map, $ это return.

Теперь я вспомнил, что мне постоянно приходится придумывать как назвать этот аргумент item каждый раз, а название ему часто и не нужно, как например в данном случае, вполне подойдёт a. Тогда я решил, что если у функции объявленой через ➮ нет параметров, то по умолчанию объявлены три параметра a, b, c. А если нужно, чтобы у функции фактически не было параметров, то надо указать явно ().

⚫data = ⚫data ⧉ (➮ { ⌥(a > 20) $ a })

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

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

Вот ещё несколько любопытных экспериментальных фич Эльфу:

A ⬊ 1 // A.push (1)

A ⬋ 22 // A.unshift (22)

n⁰ = nˣ + mⁱ // n[0] = n[x] + m[i]

⌥ (⬤ a ≟ '∅')// ⌥ (typeof a == 'undefined')

⌥ (name ≠ ⦿ && id ≠ ⦾) ⏀ ⚫name//if (name!= true && id!= false) delete this.name

ロ ⍽(⚂ * 100)// console.log (Math.floor (Math.random () * 100))

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

Многие символы настолько коротки и понятны, что стало очевидно, что скобки к аргументам после них выглядят громоздко. Пришла идея сделать скобки необязательными, в некоторых случаях. Например str ≀ 'a' аналогично str.indexOf ('a'). ≣'fs' аналогично require ('fs').

Уже более полугода, ежедневно я пользуюсь Эльфу. Он работает в node.js (и в браузере при некоторых ухищрениях аналогичных применяемых в других транспилерах, вроде coffeeScript). Я взял расширение файла .yy. Можно просто сделать:

npm i -g elfurequire ('elfu')require ('library.yy')

Все символы используемые в Эльфу это просто символы из набора Unicode. Ничего не изобретено, в болшинстве своём они из странички Unicode спецификации Math and other symbols, но есть и из рэнжей разных языков. Чтобы не было проблем, я сделал шрифт elfu.ttf в котором соединил все на данный момент используемые символы. Но на современных Linux, Windows, MacOS, iOS, Android всё из коробки отображается как надо, хотя некоторые символы берутся из разных шрифтов и могут выглядеть не очень красиво, и быть слегка разного размера.

Расширение файла .yy это отсылка на эльфийский алфавит, будем воображать, что это некий эльфийский знак, руна. На самом деле на эльфийском языке, надо говорить «Хости ламмен», что значит «Язык чисел». Впрочем, наверное надо расширение .elfu тоже обрабатываеть в require (). Кстати пакет npm elfu устанавливает три утилиты коммандной строки: yy, yyj, jyy. yy можно использовать вместо node: «yy hello.yy», yyj компилирует elfu файл в Javascript с выводом в STDOUT, jyy компилирует обратно из Javascript в Elfu.

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

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

exebook.github.io/elfu/article.htmlgithub.com/exebook/elfuwww.npmjs.com/package/elfu

Чего бы хотелось от почтенной публики, так это участия, хотя бы понарошечку. Если вас тема заинтересовала, кидайте сюда или на гитхаб ваши предложения, что можно ещё добавить или поменять. Очень много ещё Unicode символов и всяких возможностей! Даже если Эльфу останется лишь экспериментом сумасшедшего философа, многие символы могут пригодиться в других языках и разработках. Кстати, например в Эльфу стандартизованы последовательности для ввода символов по tab-completion. Например io|TAB превращается в ≀ и означает .indexOf (). Есть и готовые конфиги для Sublime Text и Geany.

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

© Habrahabr.ru