paren.md

Личный сайт Go-разработчика из Казани

Paren - это диалект языка Лисп. Он спроектирован как встроенный язык.

1;;; Комментарии 2# комментарии 3 4;; Однострочные комментарии начинаются с точки с запятой или символа решетки 5 6;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 7;; 1. Примитивные типы данных и операторы 8;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 9 10;;; Числа 11123 ; int 123.14 ; double 136.02e+23 ; double 14(int 3.14) ; => 3 : int 15(double 123) ; => 123 : double 16 17;; Обращение к функции записывается так: (f x y z ...), 18;; где f - функция, а x, y, z, ... - операнды 19;; Если вы хотите создать буквальный список данных, используйте (quote), чтобы 20;; предотвратить ненужные вычисления 21(quote (+ 1 2)) ; => (+ 1 2) 22;; Итак, некоторые арифметические операции 23(+ 1 1) ; => 2 24(- 8 1) ; => 7 25(* 10 2) ; => 20 26(^ 2 3) ; => 8 27(/ 5 2) ; => 2 28(% 5 2) ; => 1 29(/ 5.0 2) ; => 2.5 30 31;;; Логический тип 32true ; обозначает истину 33false ; обозначает ложь 34(! true) ; => false 35(&& true false (prn "досюда не доходим")) ; => false 36(|| false true (prn "досюда не доходим")) ; => true 37 38;;; Символы - это числа (int). 39(char-at "A" 0) ; => 65 40(chr 65) ; => "A" 41 42;;; Строки - это массив символов с фиксированной длиной. 43"Привет, мир!" 44"Benjamin \"Bugsy\" Siegel" ; обратная косая черта экранирует символ 45"Foo\tbar\r\n" ; включает управляющие символы в стиле Cи: \t \r \n 46 47;; Строки тоже могут объединяться! 48(strcat "Привет " "мир!") ; => "Привет мир!" 49 50;; Строка может трактоваться подобно списку символов 51(char-at "Apple" 0) ; => 65 52 53;; Выводить информацию достаточно легко 54(pr "Я" "Paren. ") (prn "Приятно познакомиться!") 55 56;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 57;; 2. Переменные 58;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 59;; Вы можете создать или инициализировать переменную, используя (set) 60;; имя переменной может содержать любой символ, исключая: ();#" 61(set some-var 5) ; => 5 62some-var ; => 5 63 64;; Обращение к переменной, прежде не определенной, вызовет исключение 65; x ; => Неизвестная переменная: x : nil 66 67;; Локальное связывание: Используйте лямбда-вычисление! `a' и `b' связывается 68;; с `1' и `2' только в пределах (fn ...) 69((fn (a b) (+ a b)) 1 2) ; => 3 70 71;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 72;; 3. Коллекции 73;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 74 75;;; Списки 76 77;; Списки подобны динамическому массиву (vector). (произвольный доступ равен O(1).) 78(cons 1 (cons 2 (cons 3 (list)))) ; => (1 2 3) 79;; `list' - это удобный конструктор списков с переменным числом элементов 80(list 1 2 3) ; => (1 2 3) 81;; и quote может также использоваться для литеральных значений списка 82(quote (+ 1 2)) ; => (+ 1 2) 83 84;; Можно еще использовать `cons', чтобы добавить элемент в начало списка 85(cons 0 (list 1 2 3)) ; => (0 1 2 3) 86 87;; Списки являются основным типом, поэтому для них предусмотрено *много* функций 88;; немного примеров из них: 89(map inc (list 1 2 3)) ; => (2 3 4) 90(filter (fn (x) (== 0 (% x 2))) (list 1 2 3 4)) ; => (2 4) 91(length (list 1 2 3 4)) ; => 4 92 93;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 94;; 3. Функции 95;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 96 97;; Используйте `fn' для создания функций. 98;; Функция всегда возвращает значение своего последнего выражения 99(fn () "Привет Мир") ; => (fn () Привет Мир) : fn 100 101;; Используйте скобки, чтобы вызвать все функции, в том числе лямбда-выражение 102((fn () "Привет Мир")) ; => "Привет Мир" 103 104;; Назначить функцию переменной 105(set hello-world (fn () "Привет Мир")) 106(hello-world) ; => "Привет Мир" 107 108;; Вы можете сократить это, используя синтаксический сахар определения функции: 109(defn hello-world2 () "Привет Мир") 110 111;; Как и выше, () - это список аргументов для функции 112(set hello 113 (fn (name) 114 (strcat "Привет " name))) 115(hello "Стив") ; => "Привет Стив" 116 117;; ... или, что эквивалентно, используйте синтаксический сахар определения: 118(defn hello2 (name) 119 (strcat "Привет " name)) 120 121;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 122;; 4. Равенство 123;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 124 125;; для чисел используйте `==' 126(== 3 3.0) ; => true 127(== 2 1) ; => false 128 129;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 130;; 5. Поток управления 131;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 132 133;;; Условный оператор 134 135(if true ; проверка выражения 136 "это - истина" ; тогда это выражение 137 "это - ложь") ; иначе другое выражение 138; => "это - истина" 139 140;;; Циклы 141 142;; Цикл for для чисел 143;; (for ИДЕНТИФИКАТОР НАЧАЛО КОНЕЦ ШАГ ВЫРАЖЕНИЕ ..) 144(for i 0 10 2 (pr i "")) ; => печатает 0 2 4 6 8 10 145(for i 0.0 10 2.5 (pr i "")) ; => печатает 0 2.5 5 7.5 10 146 147;; Цикл while 148((fn (i) 149 (while (< i 10) 150 (pr i) 151 (++ i))) 0) ; => печатает 0123456789 152 153;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 154;; 6. Изменение 155;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 156 157;; Используйте `set', чтобы назначить новое значение переменной или памяти 158(set n 5) ; => 5 159(set n (inc n)) ; => 6 160n ; => 6 161(set a (list 1 2)) ; => (1 2) 162(set (nth 0 a) 3) ; => 3 163a ; => (3 2) 164 165;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 166;; 7. Макросы 167;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 168 169;; Макросы позволяют вам расширять синтаксис языка. 170;; Paren-макросы легкие. 171;; Фактически, (defn) - это макрос. 172(defmacro setfn (name ...) (set name (fn ...))) 173(defmacro defn (name ...) (def name (fn ...))) 174 175;; Давайте добавим инфиксную нотацию 176(defmacro infix (a op ...) (op a ...)) 177(infix 1 + 2 (infix 3 * 4)) ; => 15 178 179;; Макросы приводят к неясному коду, т.е. вы можете затереть существующие переменные! 180;; Они являются кодопреобразующей конструкцией.