FSet provides several macros which are handy for updating variables that hold collections. (Their
names all end in "f", following setf.) These might appear at first glance to be mutating
operators, but of course, they’re not; they perform a functional update, reassigning the result to
the place holding the collection:
> (defparameter s (set 1 2))
S
> s
##{ 1 2 }
> (defparameter s1 s)
S1
> s1
##{ 1 2 }
> (includef s 3)
##{ 1 2 3 }
> s1
##{ 1 2 }
> (excludef s1 1)
##{ 2 }
> s
##{ 1 2 3 }
Some of these also work with maps, and there’s a setf method for @ (or
lookup). The ability, mentioned above, to specify a default for the map is very handy here:
> (defparameter m2 (empty-map 0))
M2
> m2
##{| |}/0
> (incf ( m2 'x))
1
> m2
##{| (x 1) |}/0
> (defparameter m3 (empty-map (empty-set)))
M3
> m3
##{| |}/##{}
> (includef ( m3 'foo) "bar")
##{ "bar" }
> m3
##{| (FOO ##{ "bar" }) |}/##{}
This works to multiple levels too, e.g., a map from something to maps from something else to sets.