Forth http://fforum.winglion.ru/ |
|
Язык программирования Enchilada http://fforum.winglion.ru/viewtopic.php?f=4&t=363 |
Страница 1 из 1 |
Автор: | profiT [ Пт ноя 24, 2006 10:09 ] |
Заголовок сообщения: | Язык программирования Enchilada |
Пособие по языку от автора. Дневник, посвящённый этому делу. Инструкции для скачки и запуска версии 0.4.1 интерпретатора (требует Java). Нет типов. Нет чисел. Нет строк. Только списки. Ничего, кроме списков (есть ещё выражения, но об этом как-нибудь потом, если до самого дойдёт). Если вы видите в тексте на Enchilada число 3, не обманывайте себя -- это не число, это список [() () ()]. Поэтому привычные нам операции + и * пусть и работают в Enchilada точно так же: Код: > 2 1 + 3 Но имеют иную внутренную логику: Код: > [ () () ] [ () ] + [() () ()] Таким образом + является не сложением, а конкатенацией списков: Код: > [1;2] [3;4] + [1;2;3;4] (надо ли говорить, что строки с > в начале -- это команды пользователя, а строки после команд -- вывод интерпретатором значения стека после выполнения команды?) Вы уже заметили что язык постфиксный. Через это имеем и операции возвращающие несколько результатов, и верную троицу DUP, DROP, SWAP в виде: Код: > 1 2 : 2 1 > 1 " 1 1 > 1 2 ` 1 (совсем недавно, с версии 0.4.1, автор переименовал DROP из ~ в `) (а в версии 0.4.2 вообще все стековые операции сломаны, теперь там .swap , .drop , .dup ну и плюс возможности по прямому заданию стековой нотации). - здесь унарный, является аналогом NEGATE. При этом отрицательные числа во избежания путаницы отображаются со знаком подчёркивания: Код: > 2 - _2 То есть фортовский минус мы получим комбинацией -+ : Код: > 10 2 -+ 8 Операция приведения (!): Код: > [2;4]! 2 4 > [1 2 +]! 3 > [1 2 +;3 4 +]! 3 7 То есть она выводит содержимое списка за скобки и упрощает (вычисляет) его, оставляя значения на стеке. С умножением много интереснее. Оно хоть и выдаёт для чисел понятные результаты, но выдаёт их парами: Код: > 1 2 * 2 2 Почему так -- в следующем абзаце, а пока примем как данное, что для чисел умножение логичнее комбинировать с DROP'ом: Код: > 10 2 *` 20 Произведение (*) в Enchilada является производным от Декартового произведения списков. Декартово произведение выдаёт набор всех возможных сочетаний пар составленных из элементов множеств. * выдает в первом результате левые половинки этих пар, во втором -- правые (я там сам не до конца понял...). Код: > [1;2;3] [4;5] * [1;1;2;2;3;3] [4;5;4;5;4;5] А само Декартово произведение получаем комбинированием * (умножения) и | (максимума): Код: > [1;2;3] [4;5] *| [1 4;1 5;2 4;2 5;3 4;3 5] Не спрашивайте почему именно максимум -- сам не пойму. А вообще таких отдельных непонятных мне моментов многовато.. А хотел с ними разобраться до конца, но ладно уж, пускай пока так... Через такое мы имеем что можно делать map через то же умножение, комбинируя список, который потом приводится к результату: Код: > [1 2;3 4] [*` 2+] *
[1 2;3 4] [* ` 2 +;* ` 2 +] > [1 2;3 4] [*` 2+] *| [1 2 * ` 2 +;3 4 * ` 2 +] > [1 2;3 4] [*` 2+] *|! 4 14 А, каково?.. |
Автор: | вопрос [ Пт ноя 24, 2006 11:44 ] |
Заголовок сообщения: | |
Это не язык, это скрипт какой-то... |
Автор: | profiT [ Пт ноя 24, 2006 14:33 ] |
Заголовок сообщения: | |
Дальше, как уже всегда, начинаем писать факториал на языке. Вслед за автором замечу что для определения факториала не были использованы ни циклы, ни рекурсия. Как и в случае с K или с бэкФортом нам понадобится операция генерирующая ряд натуральных чисел от 1 до n, где n -- аргумент. В определении этой функции используется то что числа в Enchilada также являются списками, пусть их элементы и пусты. Помним? Код: > 3 [1] *| [1;1;1] Или, если посмотреть с другой стороны: Код: > [1] 3 *` [1;1;1] Аналогично: Код: > [1] [1] + [1] + [1;1;1] А теперь что называется, "следи за рукой" (с): Код: > 4 ["1+] *:` [" 1 +;" 1 +;" 1 +;" 1 +] Здесь у нас в скобках по сути тело цикла, которое мы "умножаем", чтобы получить его нужное количество раз. Но циклу нужно начальное значение (чтобы самому первому " -- DUP'у было чего дублировать), поэтому добавляем единичку: Код: > 4 1:["1+] *:` 1 [" 1 +;" 1 +;" 1 +;" 1 +] Потом просто выводим "раскрученный" цикл за скобки операцией ! . Этот пример я покажу в режиме отладки: Код: > \ost 4 1:["1+] *:`! 0: 4 1 : [" 1 +] * : ` ! 1: 1 4 [" 1 +] * : ` ! 2: 1 4 [" 1 +;" 1 +;" 1 +;" 1 +] : ` ! 3: 1 [" 1 +;" 1 +;" 1 +;" 1 +] 4 ` ! 4: 1 [" 1 +;" 1 +;" 1 +;" 1 +] ! 5: 1 " 1 + " 1 + " 1 + " 1 + 6: 1 1 1 + " 1 + " 1 + " 1 + 7: 1 2 " 1 + " 1 + " 1 + 8: 1 2 2 1 + " 1 + " 1 + 9: 1 2 3 " 1 + " 1 + 10: 1 2 3 3 1 + " 1 + 11: 1 2 3 4 " 1 + 12: 1 2 3 4 4 1 + 13: 1 2 3 4 5 Последнее число нам не нужно, поэтому его надо убирать, добавляем ещё один ` -- DROP. То есть функция готова: Код: iotaN == 1:["1+] *:`!` (вот только определение функций у меня не получаются, ошибки какие-то) Заметьте, что результат функции -- ряд чисел мы получаем на стеке, а не в списке-элемента стека. Теперь нужно перемножить полученный натуральный ряд, чтобы получить факториал. Принцип такой же: Код: mulN == 1:[*`] :* ! ! Обратите внимание, mulN берёт со стека одно значение -- нужное кол-во умножений. А полностью факториал из учебника выглядит так: Код: facN == ^ [iotN; mulN] * | ! Сходу что делает facN не особо понять... Первая операция берёт значение с вершины стека и заключает его в скобки, превращая в список. Уже знакомая нам комбинация *|! делает map, но как бы наоборот... Так как у "данных" один элемент, а "функций" две, то Декартово произведение их даст последовательное выполнение обеих функций с одним и тем же аргументом: Код: 12 ^ [iotN; mulN] * | [12] [iotN; mulN] * | [12 iotN;12 mulN] Затем ! выполняет всё остальное, сначала выполняет 12 iotN , он оставляет на стеке ряд чисел, потом выполняется 12 mulN , который делает 12 нужных нам умножений на стеке, сводя всё к одному значению -- факториалу. Вот так он считается в режиме трассировки: Код: 0: 3 ^ [1 : [" 1 +] * : ` ! `;1 : [* `] : * ! !] * | !
1: [3] [1 : [" 1 +] * : ` ! `;1 : [* `] : * ! !] * | ! 2: [3;3] [1 : [" 1 +] * : ` ! `;1 : [* `] : * ! !] | ! 3: [3 1 : [" 1 +] * : ` ! `;3 1 : [* `] : * ! !] ! 4: 3 1 : [" 1 +] * : ` ! ` 3 1 : [* `] : * ! ! 5: 1 3 [" 1 +] * : ` ! ` 3 1 : [* `] : * ! ! 6: 1 3 [" 1 +] * : ` ! ` 1 3 [* `] : * ! ! 7: 1 3 [" 1 +] * : ` ! ` 1 [* `] 3 * ! ! 8: 1 3 [" 1 +] * : ` ! ` 1 [* `;* `;* `] 3 ! ! 9: 1 3 [" 1 +;" 1 +;" 1 +] : ` ! ` 1 [* `;* `;* `] 3 ! ! 10: 1 [" 1 +;" 1 +;" 1 +] 3 ` ! ` 1 [* `;* `;* `] 3 ! ! 11: 1 [" 1 +;" 1 +;" 1 +] ! ` 1 [* `;* `;* `] 3 ! ! 12: 1 " 1 + " 1 + " 1 + ` 1 [* `;* `;* `] 3 ! ! 13: 1 1 1 + " 1 + " 1 + ` 1 [* `;* `;* `] 3 ! ! 14: 1 2 " 1 + " 1 + ` 1 [* `;* `;* `] 3 ! ! 15: 1 2 2 1 + " 1 + ` 1 [* `;* `;* `] 3 ! ! 16: 1 2 3 " 1 + ` 1 [* `;* `;* `] 3 ! ! 17: 1 2 3 3 1 + ` 1 [* `;* `;* `] 3 ! ! 18: 1 2 3 4 ` 1 [* `;* `;* `] 3 ! ! 19: 1 2 3 1 [* `;* `;* `] 3 ! ! 20: 1 2 3 1 [* `;* `;* `] ! 21: 1 2 3 1 * ` * ` * ` 22: 1 2 3 3 ` * ` * ` 23: 1 2 3 * ` * ` 24: 1 6 6 ` * ` 25: 1 6 * ` 26: 6 6 ` 27: 6 Хм.. Я бы сделал как-нибудь иначе, но хояин -- барин... |
Автор: | profiT [ Пт ноя 24, 2006 14:33 ] |
Заголовок сообщения: | |
Интересно, но самую главную особенность Enchilada замечаешь не сразу. Но постепенно до тебя доходит что: -- Несмотря на то что язык стековый, стек как таковой в реализации Enchilada не нужен. -- Операции языка могут выполнятся в произвольном порядке и/или паралельно. -- Выполнение команд языка представляет собой не последовательное выполнение операций (алгоритм, программа), а что-то вроде упрощения алгебраической формулы (не зря там есть операция выведения за скобки), и последовательность команд Enchilada можно например, "объедать" с обоих концов как сосиску. Это хорошо иллюстрирует уже применённый нами режим трассировки: Код: > \ost 2 3 + 1 -+
0: 2 3 + 1 - + 1: 5 1 - + 2: 5 _1 + 3: 4 Вычисления 2 3 + и 1 - можно делать паралельно. |
Автор: | Hishnik [ Сб ноя 25, 2006 13:09 ] |
Заголовок сообщения: | |
Ну вот, опять математиков вовремя не согнали с клавиатуры |
Автор: | profiT [ Пт дек 22, 2006 17:16 ] |
Заголовок сообщения: | |
Язык и его реализация достигли стадии 0.5. Как я и говорил, в виду введения макросов наши старые, добрые DUP, SWAP мы больше не увидим. Также было полностью переписано описание языка, тем более что и сам язык довольно сильно перелицован уже к этой половинной версии, если смотреть от самого начала. Пара выдержок из описания: Цитата: Enchilada -- это полностью фукнциональный язык программирования, напоминающий конкатенативный язык Joy. Но, в отличии от Joy, Enchilada прежде всего нацелен на паралельные и распределённые вычисления.
Каждая часть Enchilada -- будь то программа, вычисление или данные -- immutable (?). И так как ничего нельзя изменить (а из этого следует что можно и безопасно разделять), использование языка сулит исключительную надёжность и расширяемость. Для наибольшей поддержки прямолинейной (?) обработки, Enchilada разработана с принципом: "как можно меньше сюрпризов": программа во время исполнения никогда не вызовет исключения. Программирование без исключений достигнуто тем, что каждый операнд в Enchilada принадлежит только одному типу: списку. Эта особенность делает язык одним из немногих языков, имеющих и строгую типизацию, и один-единственный тип данных. |
Страница 1 из 1 | Часовой пояс: UTC + 3 часа [ Летнее время ] |
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group http://www.phpbb.com/ |