Subject: Рефал и Лисп на Си++ (was: Re: интерпритатор)
From: Andrey V Stolyarov (croco@croco.net)
Date: Fri Oct 19 2001 - 20:06:39 MSD
On Fri, 19 Oct 2001, Mike Potanin wrote:
> интерпретатор (как TCL или более распространенные Perl и Python) по моему
> действительно полезен. Например Рефал силен в обработке текста вообще и
> XML вчастности. А в серверах приложений с этим часто приходится иметь
> дело. Возможность создавать эту часть приложения на Рефале и подменять на
> лету мне кажется перспективной.
Я сейчас в рамках диссертации делаю нечто из смежной области, которое,
возможно, заинтересует общественность в этом ключе. У меня Рефал (причем
полный Рефал-5, со всеми WHERE/WITH) реализован как надстройка над Лиспом.
С эффективностью, конечно, полнейший швах, ибо лисповские односвязные
списки как средство хранения рефал-выражений исключают сопоставление "с
обоих концов" со всеми вытекающими последствиями (так, в сопоставлении
'a' e.1 'c' : 'abc'
переменная e.1 будет открытой, что, конечно, с точки зрения эффективности
исполнения просто чудовищно). Но есть и плюс в виде всех достоинств Лиспа
(функции высоких порядков, замыкания, генерация кода на лету и т.д.)
В добавок все это реализовано как библиотека классов Си++ и
предназначается к применению в проектах, где основным языком является
Си++. Лисповские S-выражения представляются в виде иерархии классов Си++,
для которых для удобства перекрыты стандартные операции, включая операцию
"запятая" (используется для построения списков). Например, если
рассмотреть функцию
(defun isomorphic (tree1 tree2)
(cond ((atom tree1) (atom tree2))
((atom tree2) NIL)
(t (and (isomorphic (car tree1)
(car tree2))
(isomorphic (cdr tree1)
(cdr tree2))))))
то аналогичный код на Си++ будет выглядеть так:
#include "intelib.h"
LSymbol ISOMORPHIC("ISOMORPHIC");
void LispInit_isomorphic() {
static LSymbol TREE1("TREE1");
static LSymbol TREE2("TREE2");
(L|DEFUN, ISOMORPHIC, (L|TREE1, TREE2),
(L|COND,
(L|(L|ATOM, TREE1), (L|ATOM, TREE2)),
(L|(L|ATOM, TREE2), NIL),
(L|T, (L|AND,
(L|ISOMORPHIC, (L|CAR, TREE1),
(L|CAR, TREE2)),
(L|ISOMORPHIC, (L|CDR, TREE1),
(L|CDR, TREE2)))))).Evaluate();
}
Подчеркну, это обычный модуль Си++, не требующий никакого дополнительного
препроцессирования. Компилируется обычным компилятором Си++ (я пользуюсь
gcc 2.95.2)
Реализованный диалект Лиспа сильно усечен (массивов и структур, например,
в нем нет и не предвидится), но основные возможности Лиспа - замыкания,
функционалы, лексическое и динамическое связывание и т.п. в этот диалект
вошли. Есть, кстати, и транслятор из традиционного лисповского синтаксиса
в такой вот код на Си++. Транслятор написан на Лиспе и самоприменен.
Успешно.
Синтаксис Рефала посложнее, пришлось пофантазировать. В итоге функция
"палиндром", приведенная в качестве примера в руководстве по Рефалу-5,
выглядит в переложении так:
RFUNC(MYREFUN) [(L) ^ (L| "True")]
[(L| s_1) ^ (L| "True")]
[(L| s_1, e_2, s_1) ^ (L| (R| MYREFUN, e_2))]
[(L| e_1) ^ (L| "False")] ;
Библиотека сейчас долизывается, планирую сделать пререлиз где-то через
месяц. Пойдет, видимо, под GNU GPL (не путать с LGPL). Транслятор для
Рефала тоже планируется, но пока его нет.
Еще в планах есть, в качестве побочного эффекта от создания библиотеки,
некий новый язык (рабочее название - "Ситуационный Лисп"), представляющий
собой парадигматический гибрид Лиспа и Рефала.
Интересно ли такое кому-нибудь?
С уважением,
Андрей Столяров
This archive was generated by hypermail 2b25 : Fri Oct 19 2001 - 20:07:11 MSD