Monthly Archives: July 2014

The less-familiar parts of Lisp for beginners — slot-value

At this point in our walk through less commonly seen features of Lisp we come to the slot-value function.  This is a good place to reiterate some of the differences between the way C++ and Lisp objects are handled.

In C++, a class will typically have private and public methods.  The public methods form the user-facing API, while the private methods are used for internal implementation, and cannot be used by non-friend classes or functions.  The same goes for private and public members, other classes or functions don’t have access to private member objects.  Friends of a class are declared in the class definition, as are the public/private modifiers, so it is not possible for another function or class to manipulate the private members or methods of a class without changing the class definition itself.

In Lisp, the private/public distinction is still present, but it is not as strictly enforced.  Where C++ has public and private methods on a class, Lisp has external and internal symbols on a package.  In C++ one typically writes methods referred to as “getters” and “setters” for a member in a class, while a class in Lisp can have :reader, :writer, or :accessor methods for individual members.

So, I mentioned that Lisp does not enforce the private/public distinction as strictly as C++.  In Lisp, it is possible to use the internal symbols of a package, one has merely to use a double colon between the package name and the symbol name, rather than the usual single colon used for external symbols.  This makes it immediately obvious that the code is using symbols that are not part of the API, but means that the programmer does not have to modify the other package to cause it to export that symbol.  The equivalent for accessors is slot-value.  This function allows the programmer to read or modify (with setf), any named slot in an instance of a class, regardless of whether or not there are accessors associated with it.

When a programmer finds him or herself using internal symbols from packages, or most uses of slot-value, it’s a sign that some examination of the context may be required.  The maintainer of the package probably feels free to modify the internal symbols of his or her package without worrying about backward compatibility, as it’s not part of the API, so other code that makes use of those internal symbols may break if the package is upgraded.  Further, unlike C++, where the friends of the class are listed in the class definition, Lisp provides no similar method for the programmer changing the package to know where some code somewhere might be making use of internal symbols.

Similarly, manipulation of slots of an instance through slot-value often indicates that the programmer did not think such manipulation wise, perhaps because changes to it must accompany other changes for consistency, so a naive poking about in the innards may have unexpected results.

There are, however, some common use cases for slot-value that are expected and not suggestive of problems.  The first is exactly in the case mentioned at the end of the previous paragraph.  When a method changes two or more slots together, you do not want :writer methods that allow the manipulation of those slots individually.  You might create :reader methods, and then use slot-value with setf to change the slots together in a single method.  A second case is in setting what a C++ programmer would call a const member object.  Once more, the programmer doesn’t want to create a :writer or :accessor method for the slot, to discourage others from changing it, but that slot does have to be set during instance creation.  There, the use of slot-value is natural and preferred.

The less-familiar parts of Lisp for beginners — slot-unbound

The slot-unbound standard generic function is invoked when an attempt to read an unbound, but existing slot in an instance is made (if this explanation is unclear, please review the earlier article on slot-boundp).  Once more, this function is not for the programmer to call into, but by specializing this function it is possible to take special action when an attempt is made to read the contents of an unbound slot.

In effect, slot-unbound has the same relationship to slot-boundp that slot-missing has to slot-exists-p.

The less-familiar parts of Lisp for beginners — slot-missing

The slot-missing generic function is a function that is not intended to be invoked by the programmer, but it’s still interesting to the programmer in some contexts.  This generic function is invoked by the Lisp system when an attempt is made to retrieve from an instance the value of a slot that doesn’t exist in the class.

By specializing this function, the programmer can attach particular actions to such invalid access attemps.  The ways to access a slot by name in an object are slot-value (with or without its setf operator), slot-boundp, and slot-makunbound.  The invocation of slot-missing allows the programmer to distinguish between these cases.  One possible use would be to add debugging information or logging when one of these invalid accesses is attempted.

The less-familiar parts of Lisp for beginners — slot-makunbound

Earlier, we discussed slot-boundp.  A named slot in an instance will not be bound to a value until it has been assigned by one of several means.  An unbound slot does not have a nil value, it has no value at all, and it is an error to attempt to read its contents.

Under some circumstances, the programmer may want to take a slot that has an associated value, and return it to that pristine, unbound state.  This is what slot-makunbound does.  If the slot has a bound value, that value is discarded and the slot is returned to the unbound state.

The less-familiar parts of Lisp for beginners — slot-exists-p

In our last article, we talked about slots in classes.  I mentioned there that slot-boundp could not tell you whether a particular named slot was present in a class, it raises an error if you ask that function to act on a non-existent slot name.

So, how do you find out whether a particular object has a slot of a given name?  That’s where slot-exists-p comes in.  It returns non-nil if the named slot exists in the instance, either directly or through inheritance.

Why would a programmer want to do this?  When does the programmer not know the names of the slots in a particular class, and should he or she really be messing with a class about which they know so very little?  Well, if the coding specification for a project is sufficiently detailed, one might, for instance, say that programmer-defined classes are permitted, but not required, to define a slot called “time-last-modified”, and if that slot is defined, the code takes action to keep that slot updated.  I’ve seen it used in similar contexts, but rarely.