Подтвердить что ты не робот

Почему defun не то же самое (setq <name> <lambda>)?

Я смущен тем, как работает defun macro, потому что

(defun x () "hello")

создаст функцию x, но символ x все равно будет несвязан.

Если я привяжу некоторую лямбду к x, то x будет иметь значение, но она не будет обрабатываться интерпретатором как функция в форме, подобной этому:

(x)

Я думаю, что это связано с тем, что defun должен определять функцию в глобальной среде, но я не уверен, что именно это означает. Почему я не могу затенять его в текущей среде?

Есть ли способ заставить интерпретатора обрабатывать символ как функцию, если к нему привязана какая-то лямбда? Например:

(setq y (lambda () "I want to be a named function"))
(y)

P.S.: Я использую SBCL.

4b9b3361

Ответ 1

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

Вы определяете функции в пространстве имен функций с DEFUN, FLET, LABELS и некоторыми другими.

Если вы хотите получить объект функции как значение, вы используете FUNCTION.

(defun foo (x) (1+ x))

(function foo)   ->  #<the function foo>

или короче:

#'foo    ->   #<the function foo>

Если вы хотите вызвать функцию, вы пишете (foo 100).

Если вы хотите вызвать функцию как значение, вам нужно использовать FUNCALL или APPLY:

(funcall #'foo 1)

Вы можете передавать функции и называть их:

(defun bar (f arg)
  (funcall f arg arg))

(bar #'+ 2)  ->  4

В случае DEFUN:

Это не (setf (symbol-value 'FOO) (lambda ...)).

Это больше похоже на (setf (symbol-function 'foo) (lambda ...)).

Обратите внимание, что два пространства имен позволяют вам писать:

(defun foo (list)
  (list list))

(foo '(1 2 3))  ->  ((1 2 3))

Не существует конфликта между встроенной функцией LIST и переменной LIST. Поскольку у нас есть два разных пространства имен, мы можем использовать одно и то же имя для двух разных целей.

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

Ответ 2

Общий Lisp имеет несколько слотов для каждого символа, включая слот значения и функциональный слот. Когда вы используете синтаксис (x), общий Lisp ищет привязку к функциональному слоту x. Если вы хотите вызвать привязку значений, используйте funcall или apply.

См. http://cl-cookbook.sourceforge.net/functions.html