Spec-Zone.ru › Elisp

Определение новых форм 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; например, макрос incf Common 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

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API