Что это значит, что "Лисп можно написать сам по себе?" - PullRequest
21 голосов
/ 19 апреля 2010

Пол Грэм писал, что «Необычная вещь в Лиспе - фактически, определяющее качество Лиспа - это то, что он может быть написан сам по себе». Но это не кажется ни капелькой необычно или окончательно для меня.

ISTM, что язык программирования определяется двумя вещами: его компилятором или интерпретатором, который определяет синтаксис и семантику для языка с помощью fiat, и его стандартной библиотекой, которая в значительной степени определяет идиомы и методы, которыми обладают опытные пользователи. будет использовать при написании кода на языке.

За некоторыми конкретными исключениями (например, не являющимися членами C. Семейства .NET) стандартные библиотеки большинства языков написаны на этом языке по двум очень веским причинам: потому что они будут использовать один и тот же синтаксический набор. определения, соглашения о вызовах функций и общий «внешний вид» языка, а также потому, что люди, которые могут написать стандартную библиотеку для языка программирования, являются его пользователями, и особенно его разработчиками. Так что там нет ничего уникального; это довольно стандартно.

И снова, нет ничего уникального или необычного в том, что компилятор языка написан сам по себе. Компиляторы Си написаны на Си. Компиляторы Паскаля написаны на Паскале. Моно C # компилятор написан на C #. Черт, даже некоторые языки сценариев имеют реализации, «написанные сами по себе».

Так, что означает, что Лисп необычен в том, чтобы быть написанным сам по себе?

Ответы [ 5 ]

11 голосов
/ 19 апреля 2010

Вероятно, Павел имеет в виду, что представление синтаксиса Lisp в виде значения Lisp стандартизировано и широко распространено. Таким образом, программа на Лиспе - это просто особый вид S-выражений, и писать код на Лиспе, который манипулирует кодом на Лиспе, исключительно легко. Написание интерпретатора Lisp на Lisp - это особый случай, и он не так интересен, как общая возможность иметь единое представление как для кода, так и для данных.

7 голосов
/ 20 апреля 2010

Я только что удалил очень длинный ответ, который, вероятно, здесь неуместен.

Однако учтите, что:

  1. У LISP нет «синтаксиса», если вы подразумеваете его в значении, которое он имеет для языки как C / Java / Pascal ... есть (начальный, но настраиваемый) синтаксис для Common LISP reader , но это совсем другое (LISP о котором говорит Грэм, это не Common LISP , и читатель не язык LISP, а просто процедура). Что-то вроде "(лямбда (х) (* х 2))" это не код LISP, но текст, который, например, стандартный читатель CL может преобразовать в код LISP.

  2. LISP не только может быть написано в LISP (если вы имеете в виду способность "начальной загрузки") но оно действительно появилось таким образом . Самая первая реализация Eval в конце 1950-х был написан в LISP на бумаге, а затем преобразован вручную на машинный язык (1) : LISP начинался как чисто теоретическая идея, а не предназначен для реализации. Я не знаю другого языка программирования, который следовал этот путь. Например, C ++ был задуман как препроцессор для компилятора C и был написан на C, это не была программа C ++, позже преобразованная в C, чтобы быть в состоянии запустить его.

Есть много других аспектов, в которых LISP весьма отличается , и я думаю, что лучший способ понять это - реализовать игрушечный интерпретатор LISP (это работа меньше, чем нужно было бы особенно подумайте, если ваш «машинный язык» - это язык высокого уровня с динамической типизацией, такой как Python).

(1) в http://www -formal.stanford.edu / jmc / history / lisp / node3.html вы можете найти, как Маккарти описывает, что eval[e, a] был сначала найден на бумаге как интересный теоретический результат (реализация «универсальной функции», более точная, чем универсальная машина Тьюринга), когда для языка Лисп, который строила группа, были заложены только структуры данных и элементарные нативные функции. Эта рукописная функция была реализована вручную С.Р. Рассел в машинном коде и начал служить им первым интерпретатором Lisp.

6 голосов
/ 20 апреля 2010

Он не говорит, что Lisp можно использовать для написания компилятора Lisp. Он говорит, что язык состоит из собственных структур данных. Поэтому, хотя вы не можете создать функцию C из структур данных C, вы можете сделать это в Lisp. Программа состоит из списков, которые выполняются вашим компьютером, и эффект этих списков может заключаться в создании других списков, которые затем выполняются, а эффект этих списков может заключаться в создании еще большего количества списков, которые будут выполняться. C не имеет этого свойства. Код C не может, например, манипулировать своим собственным AST .

6 голосов
/ 19 апреля 2010

Ну, ссылка, которую вы указали, говорит о том, что если вы продолжите чтение, он подробно ответит на ваш вопрос.

Необычная вещь о Лиспе - в факт, определяющий качество Lisp-- в том, что это может быть написано само по себе. Чтобы понять, что имел в виду Маккарти это, мы собираемся проследить его шаги, с его математической записью переведено на запущенный Common Lisp Код.

4 голосов
/ 20 апреля 2010

Основная идея заключается в том, что язык Lisp имеет очень маленькое ядро ​​из нескольких функций, и основной механизм оценки может быть записан в коде на одной странице.

Это ядро ​​ Lisp .

Чтобы понять основные принципы работы языка, нужно только взглянуть на эту единственную страницу кода: она объясняет, как работают переменные, как работает вызов функций, как можно создавать новые функции и т. Д.

Только подумайте, сколько вы можете удалить из языковой реализации, чтобы добраться до основ. Каков минимальный набор примитивов и каков минимальный механизм исполнения. Чтобы написать Лисп в Лиспе, вам нужно почти ничего.

Если вы посмотрите на реализацию PASCAL (в качестве примера), она реализована не в PASCAL, а в PASCAL + с большим объемом кода, который обеспечивает необходимые структуры данных для представления языковых сущностей, парсера, компилятора, время выполнения, ... - из коробки PASCAL не предлагает много - нужно построить их (или использовать библиотеку).

Вирт (создатель Pascal) написал книгу, в которой объясняется реализация очень маленького языка, похожего на Pascal, - вам все еще нужно написать существенный код для реализации этого языка - парсер, генератор кода, время выполнения, загрузчик, .. .

Напротив, в Lisp исходный код Lisp имеет естественное представление, а основная подпрограмма, которая оценивает код Lisp, - это всего лишь одна функция Lisp. Это может не быть реальной или практической реализацией Lisp, но все же она отличается от ситуации PASCAL, где исходный код не имеет полезного представления (кроме строки или файла), а механизм выполнения гораздо больше кода.

Итак, в Лиспе мы имеем:

  • простое представление для исходного кода (списки символов)

  • простая реализация оценщика в одной маленькой функции

Кроме того, ничего не требуется для реализации оценщика Lisp в Lisp.

...