I want to know how this works:
(setf (car x) 42)
Does (car x) return an assignable reference to setf? Or is it all just macro magic? How does setf or car work?
I know passing by reference would be a terrible sin in functional programming, but I want to know how the above is done.
It's macro magic. The form (setf place value) is nothing but a specialised macro expansion. For example, (setf (car x) 42) would be translated into something like this: (rplaca x 42).
You can see how your Lisp implementation expands a SETF form using MACROEXPAND, like so (my example is using SBCL, other implementations may have completely different expansions):
CL-USER> (macroexpand '(setf (aref foo 10) 1234))
(SB-KERNEL:%ASET FOO 10 1234)
T
You can also define your own expansions:
CL-USER> (defvar *value* 0)
*VALUE*
CL-USER> (defun get-value () *value*)
GET-VALUE
CL-USER> (defun (setf get-value) (x) (setq *value* x))
(SETF GET-VALUE)
CL-USER> (setf (get-value) 42)
42
CL-USER> (get-value)
42
CL-USER> (macroexpand '(setf (get-value) 23))
(LET* ()
(MULTIPLE-VALUE-BIND (#:NEW1058) 23 (FUNCALL #'(SETF GET-VALUE) #:NEW1058)))
T
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