Смущает Лисп Цитирование - PullRequest
3 голосов
/ 23 марта 2012

У меня есть вопрос по поводу оценки списков в lisp.

Почему (a) и (+ a 1) не оцениваются,

(defun test (a) (+ a 1))

точно так же, как (print 4) здесь не оценивается

(if (< 1 2) (print 3) (print 4))

но (print (+ 2 3)) оценивается здесь

(test (print (+ 2 3)))

Это как-то связано с тем, что они являются стандартными библиотечными функциями? Могу ли я определить такие функции в моей программе lisp?

Ответы [ 3 ]

6 голосов
/ 23 марта 2012

if и defun - макросы. Макросы расширяют форму в более длинный кусок кода. Во время раскрытия ни один из аргументов макроса не оценивается.

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

Отказ от ответственности: В зависимости от того, какой тип шрифта вы используете, if и defun технически можно назвать «специальными формами», а не макросами, но концепция отложенной оценки все еще применяется.

5 голосов
/ 24 марта 2012

Как вы, вероятно, знаете, составные формы Lisp обычно обрабатываются извне. Вы должны взглянуть на символ в первой позиции самой внешней вложенности, чтобы понять форму.Этот символ полностью определяет значение формы.

;; Common Lisp: define a class A derived from B and C
(defclass a (b c) ())

;; Common Lisp: define a function of two arguments
(defun a (b c) ())

;; add A to the result of calling function B on variable C:
(+ a (b c))

Традиционно диалекты Лисп делят формы на операторные формы и формы вызова функций.Форма оператора имеет совершенно произвольное значение, определяемое фрагментом кода, который компилирует или интерпретирует эти функции (например, оценка просто повторяется по всем формам аргументов вызова функции, а полученные значения передаются в функцию).

С ранней истории Lisp позволял пользователям писать своих собственных операторов.Существовали два подхода к этому: интерпретирующие операторы (исторически известные как fexprs) и операторы компиляции, известные как макросы.Обе они основаны на идее функции, которая получает в качестве аргумента неоцененную форму, чтобы она могла реализовать собственную стратегию, расширяя тем самым модель оценки новыми поведениями.

Оператор типа fexpr просто вручаетсяформа во время выполнения, вместе с объектом среды, с помощью которого он может искать значения переменных и тому подобное.Затем этот оператор обходит форму и реализует поведение.

Макрооператору передается форма во время расширения макроса (что обычно происходит при чтении форм верхнего уровня, непосредственно перед их оценкой или компиляцией).Его задача не в том, чтобы интерпретировать поведение формы, а в том, чтобы переводить ее, генерируя код.Т.е. макрос - это мини-компилятор.(Сгенерированный код может содержать больше вызовов макросов; об этом позаботится макроэкспандер, гарантируя, что все вызовы макросов прорежены.)

Подход fexpr потерял популярность, скорее всего потому, что он неэффективен.В основном это делает компиляцию невозможной, тогда как Lisp-хакеры ценят компиляцию.(Lisp уже был скомпилированным языком примерно в 1960 году.) Подход fexpr также враждебен лексической среде;для этого требуется fexpr, являющаяся функцией, чтобы иметь возможность вглядываться в среду привязки переменных в той форме, в которой она была вызвана, что является своего рода нарушением инкапсуляции, которое не допускается лексическими областями.

Макроспись немного сложнее и в некоторых отношениях менее гибкая, чем fexprs, но поддержка написания макросов улучшалась в Лиспе с 1960-х по 70-е годы, чтобы сделать его максимально простым.Макрос изначально должен был получить всю форму, а затем должен был разобрать ее самостоятельно.Макроопределяющая система превратилась во что-то, что предоставляет макро-функции с аргументами, которые получают разбитый синтаксис в легко усваиваемых частях, включая некоторые вложенные аспекты синтаксиса.Был также разработан синтаксис обратных кавычек для написания шаблонов кода, который значительно упрощает процесс генерации кода.

Итак, чтобы ответить на ваш вопрос, как я могу сам писать такие формы?Например, если:

;; Imitation of old-fashioned technique: receive the whole form,
;; extract parts from it and return the translation.
;; Common Lisp defmacro supports this via the &whole keyword
;; in macro lambda lists which lets us have access to the whole form.
;;
;; (Because we are using defmacro, we need to declare arguments "an co &optional al",
;; to make this a three argument macro with an optional third argument, but
;; we don't use those arguments. In ancient lisps, they would not appear:
;; a macro would be a one-argument function, and would have to check the number
;; of arguments itself, to flag bad syntax like (my-if 42) or (my-if).)
;;
(defmacro my-if (&whole if-form an co &optional al)
  (let ((antecedent (second if-form))   ;; extract pieces ourselves
        (consequent (third if-form))    ;; from whole (my-if ...) form
        (alternative (fourth if-form)))
    (list 'cond (list antecedent consequent) (list t alternative))))

;; "Modern" version. Use the parsed arguments, and also take advantage of
;; backquote syntax to write the COND with a syntax that looks like the code.
(defmacro my-if (antecedent consequent &optional alternative)
   `(cond (,antecedent ,consequent) (t ,alternative))))

Это подходящий пример, потому что изначально Lisp имел только cond.Не было if в Лиспе Маккарти.Этот «синтаксический сахар» был изобретен позже, вероятно, как макрос, расширяющийся до cond, точно так же, как my-if выше.

1 голос
/ 23 марта 2012

Lisp состоит из модели оценки форм.Различные диалекты Лисп имеют разные правила для них.

Давайте посмотрим на Common Lisp.

  • данные оценивают себя
  • форма функции оценивается путем вызова функцииоцениваемые аргументы
  • специальных форм оцениваются в соответствии с правилами, определенными для каждого специального оператора.Стандарт Common Lisp перечисляет все это, определяет, что они делают неофициальным образом, и пользователь не может определить новые специальные операторы.
  • Преобразование форм макросов, результат оценивается

Как работает IF, DEFUN и т. Д. И что они оценивали, когда это делается, а что нет, определяется в стандарте Common Lisp.

...