SETFable vs place (CLHS) versus location (Norvig)
Is it setf
capable the same as the CLHS location and the Norvig PAIP location?
I'm trying to figure out what exactly is in Common Lisp, but my HyperSpec explanation
put n. 1. a form suitable for use as a generalized link. 2. the conceptual location to which such a location refers [1].
has limited help.
(I know this is not the right question for SO, but if anyone knows of a good article that explains setfable / place / location, I would appreciate the link / link)
source to share
The originally mutable data structure has a getter AND a setter. Example for car
/ rplaca
and cdr
/ rplacd
:
CL-USER 68 > (let ((a (cons 1 2)))
(print (list (car a) (cdr a)))
(rplaca a 'foo)
(rplacd a 'bar)
(print (list (car a) (cdr a)))
(values))
(1 2)
(FOO BAR)
In this example, the getter car
and cdr
to cons-cell. Settings rplaca
(replace car) and rplacd
(replace cdr).
Every changed data structure has this, and there is usually no systematic way to guess the setter name from knowing the recipient's name.
So the idea was to have a registry of getters and setters. Register a setter for the getter and the user only needs to know the recipient. The macro setf
(and others such as incf
, decf
as well as custom macros) then searches for an installer for the getter being used.
The example above with a macro setf
looks like this:
CL-USER 69 > (let ((a (cons 1 2)))
(print (list (car a) (cdr a)))
(setf (car a) 'foo)
(setf (cdr a) 'bar)
(print (list (car a) (cdr a)))
(values))
(1 2)
(FOO BAR)
As you can see, the use of rplaca
and has rplacd
been replaced by a macro setf
.
So place is basically the registered form for which the setter exists. defsetf and define-setf-expander .
define-modify-macro is used to define a macro that can change location.
For example, we can define a way to multiply the location value, similar to incf
(increase space) and decf
(decrease space).
This function is old and originally the word field was used instead of place. This way macros can use end of place with f (field).
CL-USER 71 > (define-modify-macro multf (&rest args)
* "multiply")
MULTF
CL-USER 72 > (let ((a (cons 1 2)))
(print (list (car a) (cdr a)))
(multf (car a) 2)
(multf (cdr a) 4)
(print (list (car a) (cdr a)))
(values))
(1 2)
(2 8)
source to share