Определение новых форм setf
В этом разделе описывается, как определить новые формы, на которых setf может работать.
- Макрос: gv-define-simple-setter name setter &optional fix-return
-
Этот макрос позволяет легко определять
setfметоды для простых случаев. name — имя функции, макроса или специальной формы. Вы можете использовать этот макрос, когда у name есть непосредственно соответствующая функция setter, которая обновляет его, например,(gv-define-simple-setter car setcar).Этот макрос преобразует вызов в форме
(setf (name args…) value)
в
(setter args… value)
Такой
setfвызов документирован как возвращающий value. Это не проблема для, например,carиsetcar, потому чтоsetcarвозвращает значение, которое она установила. Если ваша функция setter не возвращает value, используйте значение, отличное отnil, для аргумента fix-return макросаgv-define-simple-setter. Это расширяется в нечто эквивалентное(let ((temp value)) (setter args… temp) temp)
что гарантирует возврат правильного результата.
- Макрос: gv-define-setter name arglist &rest body
-
Этот макрос позволяет для более сложных
setfрасширений, чем предыдущая форма. Вам может потребоваться использовать эту форму, например, если нет простой функции-сеттера для вызова, или если она есть, но требует разных аргументов в форме места.Этот макрос расширяет форму
(setf (name args…) value), сначала связываяsetfаргументные формы(value args…)в соответствии с arglist, а затем выполняя body. body должен возвращать Lisp-форму, которая выполняет присваивание, и, наконец, возвращает значение, которое было установлено. Пример использования этого макроса:(gv-define-setter caar (val x) `(setcar (car ,x) ,val))
- Макрос: gv-define-expander name handler
-
Для большего контроля над расширением можно использовать макрос
gv-define-expander. Например, изменяемыйsubstringможно реализовать таким образом:(gv-define-expander substring (lambda (do place from &optional to) (gv-letplace (getter setter) place (macroexp-let2* nil ((start from) (end to)) (funcall do `(substring ,getter ,start ,end) (lambda (v) (macroexp-let2 nil v v `(progn ,(funcall setter `(cl--set-substring ,getter ,start ,end ,v)) ,v))))))))
- Макрос: gv-letplace (getter setter) place &rest body
-
Макрос
gv-letplaceможет быть полезен при определении макросов, которые работают аналогичноsetf; например, макросincfCommon Lisp может быть реализован таким способом:(defmacro incf (place &optional n) (gv-letplace (getter setter) place (macroexp-let2 nil v (or n 1) (funcall setter `(+ ,v ,getter)))))getter будет связан с копируемым выражением, возвращающим значение place. setter будет связан с функцией, которая принимает выражение v и возвращает новое выражение, которое устанавливает place в v. body должен возвращать выражение Emacs Lisp, обрабатывающее place через getter и setter.
См. исходный файл gv.el для получения дополнительной информации.
Примечание по Common Lisp: Common Lisp определяет другой способ указания поведения
setfфункции, а именноsetfфункции, имена которых представляют собой списки(setf name)а не символы. Например,(defun (setf foo) …)определяет функцию, которая используется при примененииsetfкfoo. Emacs это не поддерживает. Использованиеsetfдля формы, для которой не было определено соответствующего расширения, является ошибкой времени компиляции. В Common Lisp это не ошибка, поскольку функция(setf func)может быть определена позже.
Copyright © 1990-1996, 1998-2022 Free Software Foundation, Inc.
Licensed under the GNU GPL license.
https://www.gnu.org/software/emacs/manual/html_node/elisp/Adding-Generalized-Variables.html