Каковы задачи «читателя» при интерпретации Lisp? - PullRequest
10 голосов
/ 27 декабря 2010

Я задаюсь вопросом о цели, или, возможно, более правильно, задачах «читателя» во время интерпретации / компиляции программ на Лиспе.

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

'cheese         -->  (quote cheese)
{"a" 1 "b" 2}   -->  (array-map "a" 1 "b" 2)

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

Насколько это далеко от истины (и я слишком упростил весь процесс)?Какие еще задачи выполняет читатель?Учитывая достоинство Лиспса в том, что они гомичны (код как данные), зачем нужен лексический анализ (если он действительно сопоставим с работой читателя)?

Спасибо!

1 Ответ

20 голосов
/ 27 декабря 2010

Обычно читатель в Лиспе читает s-выражения и возвращает структуры данных.READ - это операция ввода-вывода: ввод - это поток символов, а вывод - данные Lisp.

Принтер делает наоборот: он принимает данные Lisp и выводит их как поток символов,Таким образом, он также может печатать данные Lisp во внешние s-выражения.

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

S-Expression : символические выражения.Внешнее, текстовое представление данных.Внешнее означает, что s-выражения - это то, что вы видите в текстовых файлах, строках и т. Д. Таким образом, s-выражения состоят из символов на некоторых типичных внешних носителях.

Структуры данных Lisp :символы, списки, строки, числа, символы, ...

Reader : считывает s-выражения и возвращает структуры данных Lisp.

Обратите внимание, что s-выражения такжеиспользуется для кодирования исходного кода Lisp.

В некоторых диалектах Lisp читатель программируется и управляется таблицей (через так называемую таблицу чтения).Эта таблица чтения содержит функции чтения символов.Например, символ кавычки связан с функцией, которая читает выражение и возвращает значение (выражение кавычки списка).Числовые символы 0..9 связаны с функциями, которые читают число (в действительности это может быть более сложным, поскольку некоторые Лиспы позволяют читать числа в разных базах).

S-выражения обеспечиваютвнешний синтаксис для структур данных.

Программы на Лиспе пишутся во внешней форме с использованием s-выражений.Но не все s-выражения являются допустимыми программами на Лиспе:

(if a b c d e)   is usually not a valid Lisp program

синтаксис Лисп обычно определяется поверх данных Лисп.

IF, например, имеет следующий синтаксис (в Common Lisphttp://www.lispworks.com/documentation/HyperSpec/Body/s_if.htm):

if test-form then-form [else-form]

Таким образом, он ожидает тестовую форму, затем форму и необязательную форму else.

В качестве s-выражений допустимы следующиеВыражения IF:

(if (foo) 1 2)
(if (bar) (foo))

Но поскольку программы на Лиспе являются формами, мы также можем создавать эти формы с помощью программ на Лиспе:

(список 'if' (foo) 1 2) - это программа на Лиспекоторый возвращает действительную форму IF.

CL-USER 24 > (describe (list 'if '(foo) 1 2))

(IF (FOO) 1 2) is a LIST
0      IF
1      (FOO)
2      1
3      2

Этот список может быть выполнен, например, с помощью EVAL.EVAL ожидает формы списка, а не s-выражения.Помните, что s-выражения являются только внешним представлением.Чтобы создать форму Lisp, нам нужно ПРОЧИТАТЬ ее.

Вот почему говорят, что код - это данные .Формы Lisp выражаются в виде внутренних структур данных Lisp: списки, символы, числа, строки, .... В большинстве других языков программирования код является необработанным текстом.В Лиспе s-выражения являются необработанным текстом.При чтении с помощью функции READ s-выражения превращаются в данные.

Таким образом, базовый уровень взаимодействия в Lisp называется REPL, Read Eval Print Loop.Это LOOP, который многократно читает s-выражение, оценивает форму lisp и печатает ее:

READ :  s-expression ->  lisp data
EVAL :  lisp form    ->  resulting lisp data
PRINT:  lisp data    ->  s-expression

Итак, самый примитивный REPL:

(loop (print (eval (read))))

Таким образом, с концептуальной точки зрениязрения, чтобы ответить на ваш вопрос, во время оценки читатель ничего не делает.Он не участвует в оценке.Оценка производится функцией EVAL.Читатель вызывается вызовом READ.Поскольку EVAL использует структуры данных Lisp в качестве входных данных (а не s-выражений), читатель запускается до того, как форма Lisp будет оценена (например, путем интерпретации или компиляции и выполнения).

...