You considered the idea that when you write a library (internal
module, whatever) that defines a new type of Lisp object, it should
not necessarily be apparent to the caller whether the implementation
of objects of that type happen to use CLOS.
Hans: Of course, one may want to argue that DEFCLASS forms should not
be considered to be an interface definition. Instead, one could call
for a series of DEFGENERIC forms to define the external interface of
some "module" and make class definitions be internal.
In addition to this, you'd use a factory function, rather than having
the client call make-instance, to hide the CLOS nature of the type.
I agree with you about this, except that I would go farther and use
packages.
In fact, I wrote a library in this style, called fhash. It creates an
abstraction that implements a map, just like Common Lisp hash-tables,
except that internally it uses linear search when the number of items
is small, and upgrades to to a real hash table when the number of
items gets large.
This is very much like what Hans is talking about, with one slight
difference. In the fhash library, I took the position that Common
Lisp's mechanism for encapsulation is NOT CLOS, not object-oriented
programing, but packages.
The packge declaration says:
(:export
#:fhash-table
#:make-fhash-table
#:getfhash
#:putfhash
#:remfhash
#:clrfhash
#:mapfhash
#:fhash-table-p
#:fhash-table-count
#:fhash-table-size
#:fhash-table-test
#:with-fhash-table-iterator)
More about why using packages is right, in subsequent
mail, since that could turn into a separate thread.
-- Dan
Hans Hübner wrote:
Hi,
The company I work for has a Common Lisp style guide that generally
disallows using SLOT-VALUE. Instead, accessor should be used so that:
BEFORE and :AFTER methods are always invoked when accessing a slot.
Generally, I think this is a good idea when looking at classes and
instances from the outside. Slots should be considered as being an
implementation detail, and users (i.e. client code and derived class
methods) should not make assumptions about how functionality is
implemented.
Now, I often have the need for class instances that are constant in
some respect, i.e. some properties of the instance that are
implemented using slots can't directly be changed. I often declare
such slots havin only a: READER in the class definition, which makes
the read-only nature of this slot apparent right away.
Of course, such slots need to be initialized somehow. An :INITARG
sometimes does the trick, but it is more common that the value of such
slots is calculated and recalculated during the lifetime of the
instance, and as such the slot's value must be set.
Now, from the perspective of seeing the class declaration as
documenting the visible behavior of instances of a class, it does not
seem to be proper to declare an accessor to be used in class-internal
code so that the slot's value can be updated. Instead, I think that
it is better to use SLOT-VALUE to mess with the guts of an instance
from code that is part of the guts itself.
Of course, one may want to argue that DEFCLASS forms should not be
considered to be an interface definition. Instead, one could call for
a series of DEFGENERIC forms to define the external interface of some
"module" and make class definitions be internal. From a more practical
perspective, though, class definitions in CL serve both as interface
and implementation definition, thus it seems to be appropriate using
the mechanisms provided by CLOS to support both uses.
How do others use or avoid SLOT-VALUE? Is it frowned upon in your
company's or project's (verbal) style guide?
Thanks for your input,
Hans
------------------------------------------------------------------------
_______________________________________________
pro mailing list
pro@common-lisp.net
http://common-lisp.net/cgi-bin/mailman/listinfo/pro
_______________________________________________
pro mailing list
pro@common-lisp.net
http://common-lisp.net/cgi-bin/mailman/listinfo/pro