Как работает функция SETF для расширения SETF?

В практическом Common Lisp, глава 17. Переориентация объектов: раздел классов Функции доступа, мне было трудно понять, как SETF расширяется.

Функции:

(defun (setf customer-name) (name account)
  (setf (slot-value account 'customer-name) name))

bank-account определение класса:

(defclass bank-account ()
  ((customer-name
    :initarg :customer-name
    :initform (error "Must supply a customer name."))
   (balance
    :initarg :balance
    :initform 0)
   (account-number
    :initform (incf *account-numbers*))
   account-type))

Что я не понимаю

  • в выражении (setf (customer-name my-account) "Sally Sue") делает (customer-name my-account) вернуть значение слота SETFable customer-name класса bank-account который тогда SETF использует для установки значения "Sally Sue"?

  • является (setf (customer-name my-account) "Sally Sue") на самом деле вызов функции выше?

  • как определено выше, setf customer-name функция?

  • в функции выше customer-name в (setf customer-name) а также 'customer-name в теле имеется в виду одно и то же?

  • раздел утверждает

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

    если это так, то зачем использовать slot-value функция внутри определения функции, когда функция может быть использована для доступа к месту?

2 ответа

Во многих случаях для доступа к данным и их настройки необходимы две вещи:

  • способ извлечь что-то из структуры данных
  • способ установить что-то в структуре данных

Таким образом, можно определить функцию установки и функцию получения. Для простых случаев они также могут выглядеть просто. Но для сложных случаев они не могут. Теперь, если вы знаете имя получателя, как называется этот установщик? Или: если вы знаете имя установщика, как называется получатель?

Common Lisp считает, что вам нужно знать только имя получателя.

  • геттер называется, скажем, GET-FOO

  • тогда вызывается функция установки (SETF GET-FOO), Всегда.

  • функция setter может быть вызвана следующим образом: (setf (get-foo some-bar) new-foo), Всегда.

Так ты пишешь GET-FOO функция. Вы также пишете (SETF GET-FOO) функция и Common Lisp регистрирует его как функцию-установщик.

(SETF GET-FOO) это список. Это также название функции. Здесь у нас есть исключение: Common Lisp иногда допускает список в качестве имени функции. Таким образом, не все имена функций являются символами, некоторые на самом деле являются списками.

(setf (customer-name my-account) "Sally Sue") на самом деле вызов определенного установщика. my-account переменная, значение которой будет связано с account переменная сеттера. "Sally Sue" является строкой, и она будет связана с name переменная сеттера.

Как разработчик, вы должны знать только геттер:

  • использование геттера: (customer-name my-account)

  • использование сеттера: (setf (customer-name my-account) "Sally Sue"), SETF это макрос, который расширяется до вызова функции установки.

(defun (setf customer-name) (name account)
  (setf (slot-value account 'customer-name) name))

Выше определяется функция setter, называемая (setf customer-name),

CL-USER 80 > (function (setf customer-name))
#<interpreted function (SETF CUSTOMER-NAME) 40A00213FC>

Когда функция вызывается через SETF макрос вызывает другой установщик - на этот раз используя доступ к значению слота через имя слота.

setf это очень сложный макрос, который знает, как декодировать свой первый аргумент, который обычно выглядит как вызов функции, как "место", а затем вызывает любые формы, необходимые для установки места в новое значение. Это не полезно думать о (customer-name my-account) возвращая что-либо в setf выражение. setf макрос применяет правила, определенные в HyperSpec, к своей форме места и, как случай по умолчанию, преобразует

(setf (foo arg0 arg1 ...) new-val)

в

(funcall #'(setf foo) new-val arg0 arg1 ...)

Отрывок из Практического Common Lisp объясняет, в несколько эллиптическом ключе, что происходит за кулисами, когда вы указываете :accessor вариант в defclass определение слота.

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