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
формы не содержит имя функции. Это может быть только символ или лямбда-выражение (хотя реализации могут разрешать другие форматы в качестве расширений).