Мы рассматриваем программу Lisp как данные/S-выражения/деревья из-за существования читателя , первая часть Lisp, которую видит ваша программа. Читатель
- превращает ваш текст программы в структуру данных ...
- которые можно манипулировать (с помощью макросов).
Эта структура данных является рекурсивной - ее элементы могут быть схожими структурами данных - и так это происходит и так далее.
Например, выражение в ответ Хирона, (+ (* 8 8) (* 4 4))
, преобразуется читателем в
(clojure.lang.PersistentList
[clojure.lang.Symbol +]
(clojure.lang.PersistentList
[clojure.lang.Symbol *]
[java.lang.Long 8]
[java.lang.Long 8])
(clojure.lang.PersistentList
[clojure.lang.Symbol *]
[java.lang.Long 4]
[java.lang.Long 4]))
где каждый элемент имеет свой тип перед ним.
- литералы, такие как
4
полностью оцениваются;
- символы, такие как
+
, и структуры данных, такие как списки, распознаются и построены.
Вы можете видеть списки, представляющие подвыражения внутри списка, представляющие все выражение.
Lisp рассматривает каждый список как применение первого элемента - оператора - к другим элементам в качестве аргументов. Таким образом, каждый оператор имеет число (которое может быть нулем) элементов под ним. Таким образом, мы рассматриваем иерархию списков как дерево.
- Это не относится к другим структурам данных манифеста: векторам, наборам и картам.
- Если оператор является функцией, он работает, когда программа запускается. Если это макрос, он работает сразу в структуре, построенной читателем.
Функция read-string
показывает структуру, которую читатель произведет из текстового выражения. Это неинформативно само по себе, так как печать просто реконструирует текст в стандартном формате.
(read-string "(+ ( * 8 8)
(* 4 4))")
; (+ (* 8 8) (* 4 4))
Функция, которая подвергается структуру, маркированный ее типов
(defn typed [form]
(if (sequential? form)
(cons (type form) (map typed form))
[(type form) form]))
называется так:
(typed (read-string "(+ (* 8 8) (* 4 4))"))