Автор оригіналу використовував символ#для коментарів, але Друкарня не відображає такий код коректно, і коментарі зливаються з іншими частинами коду. Читати коментарі на телефонах стає ще складніше через автоматичне перенесення рядків. Тому я вирішив замінити символ#на стандартний//. Майте це на увазі.
Перед усім, ми повинні чітко уявити, що ми намагаємося досягти. Це хороша ідея підготувати детальний опис граматики, але в цьому посібнику я буду триматися більш неформального стилю, тому ось мова за допомогою прикладів:
// Це коментар
println("Hello World!");
println(2 + 3 * 4);
// Функції вводяться за допомогою "lambda" або "λ"
fib = lambda (n) if n < 2 then n else fib(n - 1) + fib(n - 2);
println(fib(15));
print-range = λ(a, b) // "λ" синонім до "lambda"
if a <= b then { // `then` тут, необов'язкове, як видно
print(a);
if a + 1 <= b {
print(", ");
print-range(a + 1, b);
} else println(""); // перехід на новий рядок
};
print-range(1, 5);Зверніть увагу, що імена ідентифікаторів можуть містити символ мінуса (print-range). Це питання особистого смаку: я завжди ставлю пробіли навколо операторів, мені не дуже подобається camelCaseNames, і дефіс виглядає краще, ніж підкреслення. Чудова річ у створенні своєї мови - це можливість робити все так, як вам подобається. :)
Вивід:
Hello World!
14
610
1, 2, 3, 4, 5Мова схожа на JavaScript, але відрізняється. По-перше, тут немає операторів (statements), лише вирази (expressions).
Вираз повертає значення і може бути використаний на місці будь-якого іншого виразу. Крапки з комою потрібні для розділення виразів у "послідовності". Фігурні дужки, { та }, створюють таку послідовність і самі є виразом. Їх значення - це значення, яке повертає останній вираз. Наступне є правильною програмою:
a = {
fib(10); // не має побічних ефектів, але все одно обчислюється
fib(15) // останньої крапки з комою може не бути
};
print(a); // вихід: 610Функції вводяться за допомогою одного з ключових слів lambda або λ (вони є синонімами). Після ключового слова має бути (можливо, пустий) список змінних, розділених комами у дужках, як у JavaScript — це назви аргументів. Тіло функції є одним виразом, але воно може бути послідовністю, обгорнутою у {…}. Немає оператора return (немає операторів) — останній вираз, що обчислюється в функції, визначає значення, яке повертається її викликачу.
Немає var. Для введення нових змінних можна використовувати те, що JavaScript-розробники називають "IIFE". Використовуйте lambda, оголошуйте змінні як аргументи. Змінні мають область видимості функції, а функції є замиканнями — так, як у JavaScript.
Навіть if є сам по собі виразом. У JavaScript ви могли б досягти цього ефекту за допомогою тернарного оператора:
a = foo() ? bar() : baz(); // JavaScript
a = if foo() then bar() else baz(); // λanguageКлючове слово then є необов'язковим, коли гілка починається з відкритої фігурної дужки ({), як можна побачити в прикладі print-range вище. В іншому випадку воно обов'язкове. Ключове слово else обов'язкове, якщо альтернативна гілка присутня. Знову ж таки, then і else приймають як тіло один вираз, але ви можете {групувати} кілька виразів, використовуючи фігурні дужки та крапки з комами. Коли відсутня гілка else і умова є false, результат виразу if є false. Говорячи про це, false - ключове слово, що позначає єдине хибне значення в нашій λanguage:
if foo() then print("OK");виведе "OK" тільки тоді, коли результат виклику foo() НЕ дорівнює false. Є також ключове слово true для повноти, але, справді, все, що не є false (за оператором === у JavaScript), буде розглядатися як true в умовних виразах (включаючи число 0 і пустий рядок "").
Також слід зауважити, що немає потреби вимагати дужок навколо умови if. Це не викличе виключення, якщо ви їх додасте, але, оскільки відкрита дужка починає вираз, вони просто зайві.
Весь програмний код розбирається так, ніби він вбудований у фігурні дужки, тому після кожного виразу потрібно ставити крапку з комою. Останній вираз може бути винятком.
Отже, це наша маленька λanguage. Вона не обов'язково є хорошою. Синтаксис виглядає миленьким, але в ньому є свої пастки. Багато чого не вистачає, наприклад, об'єктів або масивів; ми не зосереджуємося на них, тому що вони не є важливими для нашого подорожі. Якщо ви зрозуміли весь цей матеріал, ви зможете легко реалізувати їх.
У наступному розділі ми напишемо парсер для λanguage.