Выразительный JavaScript (Хавербеке) - страница 122

Мошенничество

Когда мы определяли >if и >while, вы могли заметить, что они представляли собой простые обёртки вокруг >if и >while в JavaScript. Значения в Egg – также обычные значения JavaScript.

Сравнивая реализацию Egg, построенную на JavaScript, с объёмом работы, необходимой для создания языка программирования непосредственно на машинном языке, то разница становится огромной. Тем не менее, этот пример, надеюсь, даёт вам представление о работе языков программирования.

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

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

Или представьте, что вы строите гигантского робота-динозавра и вам нужно запрограммировать его поведение. JavaScript – не самый эффективный способ сделать это. Можно вместо этого выбрать язык примерно такого свойства:

>behavior walk

>  perform when

>    destination ahead

>  actions

>    move left-foot

>    move right-foot


>behavior attack

>  perform when

>    Godzilla in-view

>  actions

>    fire laser-eyes

>    launch arm-rockets

Обычно это называют языком для выбранной области (domain-specific language) – язык, специально предназначенный для работы в узком направлении. Такой язык может быть более выразительным, чем язык общего назначения, потому что он разработан для выражения именно тех вещей, которые надо выразить в этой области – и больше ничего.

Упражнения

Массивы

Добавьте поддержку массивов в Egg. Для этого добавьте три функции в основную область видимости: >array(...) для создания массива, содержащего значения аргументов, >length(array) для возврата длины массива и >element(array, n) для возврата n-ного элемента.

>// Добавьте кода

>topEnv["array"] = "...";

>topEnv["length"] = "...";

>topEnv["element"] = "...";


>run("do(define(sum, fun(array,",

>    "     do(define(i, 0),",

>    "        define(sum, 0),",

>    "        while(<(i, length(array)),",

>    "          do(define(sum, +(sum, element(array, i))),",

>    "             define(i, +(i, 1)))),",

>    "        sum))),",

>    "   print(sum(array(1, 2, 3))))");

>// → 6

Замыкания

Способ определения >fun позволяет функциям в Egg замыкаться вокруг окружения, и использовать локальные переменные в теле функции, которые видны во время определения, точно как в функциях JavaScript.

Следующая программа иллюстрирует это: функция