The Common Lisp HyperSpec covers the with-slots macro. However, the example is hard to grasp.
Is there an easier and more didactic example about it?
The Common Lisp HyperSpec covers the with-slots macro. However, the example is hard to grasp.
Is there an easier and more didactic example about it?
On
Yes. This (great) tutorial of 2003 has a good one from the geometry domain.
Create a class to represent points in 3-dimensions:
(defclass point ()
(x y z))
Create a variable to instantiate the class and a function to set the values:
(defvar my-point
(make-instance 'point))
(defun set-point-values (point x y z)
(setf (slot-value point 'x) x
(slot-value point 'y) y
(slot-value point 'z) z))
In the REPL, do:
CL-USER 17 > (set-point-values my-point 3 4 12)
12
Now, think about a function to compute the distance between points. A brute force way would be:
(defun brute-force-distance-from-origin (point)
(let ((x (slot-value point 'x))
(y (slot-value point 'y))
(z (slot-value point 'z)))
(sqrt (+ (* x x)
(* y y)
(* z z)))))
Using the with-slots macro:
(defun distance-from-origin (point)
(with-slots (x y z) point (sqrt (+ (* x x)
(* y y)
(* z z)))))
Calling the function in the REPL works as expected:
CL-USER> (distance-from-origin my-point)
13.0
To better understand with-slots, one should look into defclass first.
It means that, unless specific request,
defclassdon't create any accessor for the slots:In this case, one must use the slot-value function to access or modify the slot value.
Obviously, when there are several slots to update, the code become a little cumbersome:
For that reason, the with-slots macro can make the code easier to read: