In Practical Common Lisp chapter 17. Object Reorientation: Classes section Accessor Functions, I was finding it difficult understanding the way SETF
is being extended.
The functions:
(defun (setf customer-name) (name account)
(setf (slot-value account 'customer-name) name))
bank-account
class definition:
(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))
What I don't understand:
in the expression (setf (customer-name my-account) "Sally Sue")
does (customer-name my-account)
return a SETFable slot-value customer-name
of the the class bank-account
which then SETF
uses to set the value to "Sally Sue"?
is (setf (customer-name my-account) "Sally Sue")
actually calling the function above?
as defined above is setf customer-name
a function?
in the function above is customer-name
in (setf customer-name)
and 'customer-name
in the body referring to the same thing?
the section states
second element is a symbol, typically the name of a function used to access the place the SETF function will set
if that's the case then why use the slot-value
function inside the function's definition when the function can be used to access the place?
setf is actually a macro that examines an access form and produces a call to the corresponding update function. Given the existence of setf in Common Lisp, it is not necessary to have setq, rplaca, and set; they are redundant. They are retained in Common Lisp because of their historical importance in Lisp.
What is the difference between setf and setq? Explanation: Setq is used only for setting the values of symbols but setf can be used for anything. Setf can be used for setting value of any data-type and not only symbols.
(setq var1 form1 var2 form2 ...) is the simple variable assignment statement of Lisp. First form1 is evaluated and the result is stored in the variable var1, then form2 is evaluated and the result stored in var2, and so forth. setq may be used for assignment of both lexical and dynamic variables.
The let expression is a special form in Lisp that you will need to use in most function definitions. let is used to attach or bind a symbol to a value in such a way that the Lisp interpreter will not confuse the variable with a variable of the same name that is not part of the function.
In many cases accessing and setting data, one needs two things:
Thus one would define a setter function and a getter function. For simple cases they also may look simple. But for complex cases they may not. Now if you know the name of the getter, what is the name of the setter? Or: if you know the name of the setter, what is the name of the getter?
Common Lisp has the idea that you only need to know the name of the getter.
the getter is called, say, GET-FOO
then the setter function is called (SETF GET-FOO)
. Always.
the setter function can be invoked this way: (setf (get-foo some-bar) new-foo)
. Always.
So you write the GET-FOO
function. You also write the (SETF GET-FOO)
function and Common Lisp registers it as a setter function.
(SETF GET-FOO)
is a list. It's also the name of a function. Here we have the exception: Common Lisp sometimes allows a list as a function name. Thus not all function names are symbols, some are actually lists.
(setf (customer-name my-account) "Sally Sue")
is actually a call the the defined setter. my-account
is a variable whose value will be bound to the account
variable of the setter. "Sally Sue"
is a string and it will be bound to the name
variable of the setter.
As a developer you only have to know the getter:
use of the getter: (customer-name my-account)
use of the setter: (setf (customer-name my-account) "Sally Sue")
. SETF
is a macro, which expands into a call of the setter function.
(defun (setf customer-name) (name account)
(setf (slot-value account 'customer-name) name))
Above defines a setter function called (setf customer-name)
.
CL-USER 80 > (function (setf customer-name))
#<interpreted function (SETF CUSTOMER-NAME) 40A00213FC>
When the function gets called via the SETF
macro, it calls another setter - this time using the access to a slot value via the slot name.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With