Setf имена функций

Чтение этого вопроса заставило меня задуматься о том, что представляет собой действительный автомобиль выражения. Очевидно, что символы и лямбды можно "вызывать", используя обычный синтаксис. По словам гиперспека,

имя функции n. 1. (в среде) Символ или список (символ setf), который является именем функции в этой среде. 2. Символ или список (символ setf).

Итак, теоретически (setf some-name) это имя функции. Я решил попробовать.

(defun (setf try-this) ()
  (format t "Don't name your functions like this, kids :)"))

((setf try-this))
(funcall '(setf try-this))
(setf (try-this))

GNU CLISP, SBCL и ABCL позволят мне определить эту функцию. Однако SBCL и ABCL не позволяют мне вызывать его, используя любой из синтаксисов, показанных во фрагменте. CLISP, с другой стороны, будет запускать первые два, но все еще ошибается на третьем.

Мне интересно, какой компилятор ведет себя правильно. Поскольку SBCL и ABCL согласны, я рискну предположить, что правильная реализация должна отклонить этот код. В качестве второго вопроса, как бы я назвал мою невероятно изощренную бесполезную функцию из фрагмента кода, поскольку то, что я пробовал выше, не работает переносимо. Или, может быть, более полезно,

1 ответ

Решение

SETF Функция должна принимать хотя бы один аргумент, который является новым значением, которое будет сохранено в этом месте. Он также может принимать дополнительные аргументы, они будут заполнены из аргументов в выражении place в вызове SETF,

Когда вы используете SETFу него должно быть четное количество аргументов: каждому месту, которому вы назначаете, нужно присваивать значение.

Так и должно быть:

(defun (setf try-this) (new-value) 
    (format t "You tried to store ~S~%" new-value))
(setf (try-this) 3)
(funcall #'(setf try-this) 'foo)

Вы не можете использовать

((setf try-this) 'bar)

поскольку car формы не содержит имя функции. Это может быть только символ или лямбда-выражение (хотя реализации могут разрешать другие форматы в качестве расширений).

Другие вопросы по тегам