Почему #' используется перед лямбдой в языке Common LISP?

Я хотел бы знать, почему наиболее распространенный код Lisp, который я вижу, имеет вещи как

(mapcar #'(lambda (x) (* x x)) '(1 2 3))

вместо просто

(mapcar (lambda (x) (* x x)) '(1 2 3)),

который, кажется, работает также. Я начинаю изучать язык Common LISP и имею некоторые знания в Схеме, это заинтриговывает меня.

Править: Я знаю, что Вам нужен #' с именами функций, потому что они живут в другом пространстве имен, чем переменные. Мой вопрос примерно #' перед лямбдой, поскольку лямбда уже возвращает функциональный объект (я думаю). То, что # '-less работа лямбд из-за макрорасширения просто делает это более интригующим...

35
задан Vítor De Araújo 24 July 2010 в 15:25
поделиться

1 ответ

#'foo - это сокращение для (function foo) читателя.

В CL существует несколько различных пространств имен, #'foo или (function foo) вернут функциональное значение от foo.

Возможно, вы захотите поискать "Lisp-1 vs. Lisp-2", проверить другие вопросы на Stackoverflow или прочитать старую статью Питмана и Габриэля, чтобы узнать больше о концепции множественных пространств имен (также называемых слотами или ячейками символов).

Причина, по которой в случае с лямбдой #' может быть опущен в CL, заключается в том, что это макрос, который расширяется таким образом (взято из Hyperspec):

(lambda lambda-list [[declaration* | documentation]] form*)
==  (function (lambda lambda-list [[declaration* | documentation]] form*))
==  #'(lambda lambda-list [[declaration* | documentation]] form*)

#' может все еще использоваться по историческим причинам (я думаю, что в Maclisp лямбды не расширялись до формы функции), или потому что некоторые люди считают, что обозначение лямбд шарп-кавычками может сделать код более читабельным или связным. Возможно, есть какие-то особые случаи, в которых это имеет значение, но в целом, не имеет значения, какую форму вы выберете.

Думаю, вы можете думать об этом следующим образом: (function (lambda ...)) возвращает функцию, которую (lambda ...) создает. Обратите внимание, что lambda в CL Hyperspec имеет как макрос, так и запись символа. Из последнего:

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

Из документации по function:

Если name является лямбда-выражением, то возвращается возвращается лексическое закрытие.

Я думаю, что разница также связана с вызовом лямбда-форм следующим образом: ((lambda ...) ...), где она рассматривается как форма, которую нужно оценить, против (funcall #'(lambda ...) ...). Если вы хотите почитать больше на эту тему, есть тема c.l.l об этом.

Некоторые цитаты из этой темы:

(лямбда (x) ... сама по себе является просто некоторой структура списка без кавычек. Это ее появление в качестве аргумента в специальной формы ФУНКЦИИ (функция (лямбда (x) ... приводит к тому, что существование объекта функции

и:

Дело осложняется еще и тем, что макрос LAMBDA был довольно поздним добавлением в ANSI Common Lisp, поэтому все действительно старые парни (т.е. такие как я) изучали свой лисп, когда вам нужно было добавлять #' к лямбда-выражению в функциях отображения. В противном случае несуществующая лямбда-функция была бы вызвана.

Добавление макроса изменило это, но некоторые из нас слишком закостенели в своих взглядах, чтобы чтобы захотеть меняться.

39
ответ дан 27 November 2019 в 07:17
поделиться
Другие вопросы по тегам:

Похожие вопросы: