From: Michael Park
Subject: classes and structs
Date: 
Message-ID: <ff20888b.0305192128.2e6f7000@posting.google.com>
Why aren't classes as convenient to use as structs? Structs define
default accessors automatically. Structs can also be read and printed.
Why not classes?

From: Brian Seitz
Subject: Re: classes and structs
Date: 
Message-ID: <bad8ec$6ri$1@tomm.stsci.edu>
Michael Park wrote:
> Why aren't classes as convenient to use as structs? Structs define
> default accessors automatically. Structs can also be read and printed.
> Why not classes?

It's pretty easy to make class-defining macro that automatically makes 
accessors.  If you wanted to put some sort of prefix on the accessor, 
you could just do an (intern (format)).

(defmacro defop-class (name inherit slots)
   "Define a class with slots with identity accessors and initform nil."
   (let ((slot-defs (mapcar #'(lambda (slot)
			       `(,slot :accessor ,slot :initform nil))
			   slots)))
     `(defclass ,name ,inherit ,slot-defs)))

(defop-class my-class (my-parent-class)
   (slot1 slot2 slot3))

expands to:
(DEFCLASS MY-CLASS (MY-PARENT-CLASS)
           ((SLOT1 :ACCESSOR SLOT1 :INITFORM NIL)
            (SLOT2 :ACCESSOR SLOT2 :INITFORM NIL)
            (SLOT3 :ACCESSOR SLOT3 :INITFORM NIL)))

Hrm, I guess this is one of those 'write it yourself!' answers some 
people hate so much.
From: Jock Cooper
Subject: Re: classes and structs
Date: 
Message-ID: <m365o5h6e6.fsf@jcooper02.sagepub.com>
Brian Seitz <······@stsci.edu> writes:

> Michael Park wrote:
> > Why aren't classes as convenient to use as structs? Structs define
> > default accessors automatically. Structs can also be read and printed.
> > Why not classes?
> 
> It's pretty easy to make class-defining macro that automatically makes
> accessors.  If you wanted to put some sort of prefix on the accessor,
> you could just do an (intern (format)).
> 
> (defmacro defop-class (name inherit slots)
>    "Define a class with slots with identity accessors and initform nil."
>    (let ((slot-defs (mapcar #'(lambda (slot)
> 			       `(,slot :accessor ,slot :initform nil))
> 			   slots)))
>      `(defclass ,name ,inherit ,slot-defs)))
> 
> (defop-class my-class (my-parent-class)
>    (slot1 slot2 slot3))
> 
> expands to:
> (DEFCLASS MY-CLASS (MY-PARENT-CLASS)
>            ((SLOT1 :ACCESSOR SLOT1 :INITFORM NIL)
>             (SLOT2 :ACCESSOR SLOT2 :INITFORM NIL)
>             (SLOT3 :ACCESSOR SLOT3 :INITFORM NIL)))
> 
> Hrm, I guess this is one of those 'write it yourself!' answers some
> people hate so much.

I wrote something similar just to save typing.  I wanted to 
be able to specify a "conc-name" and optional default values.
It would be pretty simple to support other things like using
reader/writer vs. accessor, or specifying a superclass list, etc.
here it is:

(defmacro defclassifier (class &rest slotnames)
  (let (classname classtext concname)
    (etypecase class
      (cons (setq classname (car class)
		  classtext (symbol-name (car class))
		  concname (string-upcase (cadr class))))
      (atom (setq classname class
		  classtext (symbol-name class)
		  concname (symbol-name classname))))
    `(defclass ,classname ()
      ,(do* ((slotcdr slotnames (cdr slotcdr))
	     (slotname (car slotcdr) (car slotcdr))
	     slottext
	     (slotform nil nil)
	     result)
	    ((null slotcdr) (nreverse result))
	    (etypecase slotname
	      (cons (setq slottext (symbol-name (car slotname))
			  slotform (cadr slotname)
			  slotname (car slotname)))
	      (atom (setq slottext (symbol-name slotname))))
	    (push `(,slotname :initarg ,(intern slottext "KEYWORD") :initform ,slotform
		    :accessor ,(intern (concatenate 'string concname "-" slottext))) result)))))

So you can say

(defclassifier foo  bar baz quz)

to give

(defclass foo ()
 ((bar :initarg :bar :initform nil :accessor foo-bar)
  (baz :initarg :baz :initform nil :accessor foo-baz)
  (qux :initarg :qux :initform nil :accessor foo-qux)))

or a little more fancy

(defclassifier (foo-class "fc")   ; this is like conc-name
 (bar :default-bar)               ; to specify :initform
 baz 
 (qux "hi mom"))

which gives

(defclass foo-class ()
 ((bar :initarg :bar :initform :default-bar :accessor fc-bar)
  (baz :initarg :baz :initform nil :accessor fc-baz)
  (qux :initarg :qux :initform "hi mom" :accessor fc-qux)))


-----------
Jock Cooper
http://www.fractal-recursions.com
From: Joe Marshall
Subject: Re: classes and structs
Date: 
Message-ID: <r86th4dw.fsf@ccs.neu.edu>
Jock Cooper <·····@mail.com> writes:

> So you can say
> 
> (defclassifier foo  bar baz quz)
> 
> to give
> 
> (defclass foo ()
>  ((bar :initarg :bar :initform nil :accessor foo-bar)
>   (baz :initarg :baz :initform nil :accessor foo-baz)
>   (qux :initarg :qux :initform nil :accessor foo-qux)))

Bonus question:  Why is this not a good idea?
(Hint:  the accessors are generic functions.)
From: Steven E. Harris
Subject: Re: classes and structs
Date: 
Message-ID: <q67addhjvtf.fsf@raytheon.com>
Joe Marshall <···@ccs.neu.edu> writes:

> Bonus question:  Why is this not a good idea?
> (Hint:  the accessors are generic functions.)

Because the chosen naming conflates the specific class defined here
with generic function names that could be applicable to a broad set of
classes (that don't need to be related through inheritance)?

-- 
Steven E. Harris        :: ········@raytheon.com
Raytheon                :: http://www.raytheon.com
From: Joe Marshall
Subject: Re: classes and structs
Date: 
Message-ID: <llx1gzoq.fsf@ccs.neu.edu>
Steven E. Harris <········@raytheon.com> writes:

> Joe Marshall <···@ccs.neu.edu> writes:
> 
> > Bonus question:  Why is this not a good idea?
> > (Hint:  the accessors are generic functions.)
> 
> Because the chosen naming conflates the specific class defined here
> with generic function names that could be applicable to a broad set of
> classes (that don't need to be related through inheritance)?

You get the cigar!
From: sv0f
Subject: Re: classes and structs
Date: 
Message-ID: <none-AA49F6.11533121052003@news.vanderbilt.edu>
In article <············@ccs.neu.edu>, Joe Marshall <···@ccs.neu.edu> 
wrote:

>Steven E. Harris <········@raytheon.com> writes:
>
>> Joe Marshall <···@ccs.neu.edu> writes:
>> 
>> > Bonus question:  Why is this not a good idea?
>> > (Hint:  the accessors are generic functions.)
>> 
>> Because the chosen naming conflates the specific class defined here
>> with generic function names that could be applicable to a broad set of
>> classes (that don't need to be related through inheritance)?
>
>You get the cigar!

And even if they are related by inheritance, because the
accessor methods are automatically generated, they will
not invoke CALL-NEXT-METHOD.  Therefore, the primary
methods of superclasses may inadvertently not be called.

Is this corollary true?
From: Joe Marshall
Subject: Re: classes and structs
Date: 
Message-ID: <ptmcf7g8.fsf@ccs.neu.edu>
sv0f <····@vanderbilt.edu> writes:

> In article <············@ccs.neu.edu>, Joe Marshall <···@ccs.neu.edu> 
> wrote:
> 
> >Steven E. Harris <········@raytheon.com> writes:
> >
> >> Joe Marshall <···@ccs.neu.edu> writes:
> >> 
> >> > Bonus question:  Why is this not a good idea?
> >> > (Hint:  the accessors are generic functions.)
> >> 
> >> Because the chosen naming conflates the specific class defined here
> >> with generic function names that could be applicable to a broad set of
> >> classes (that don't need to be related through inheritance)?
> >
> >You get the cigar!
> 
> And even if they are related by inheritance, because the
> accessor methods are automatically generated, they will
> not invoke CALL-NEXT-METHOD.  Therefore, the primary
> methods of superclasses may inadvertently not be called.
> 
> Is this corollary true?

Yes.

And if you start using around or before or after methods on the
superclass, then you'd see it even more.  The subclass would share the
slot, but there would be two accessors defined for the slot, one that
used the around method, and one that didn't.  Lot's of fun debugging
that one!  Likewise if you explicitly called CALL-NEXT-METHOD.
From: Jock Cooper
Subject: Re: classes and structs
Date: 
Message-ID: <m3of1w7xgx.fsf@jcooper02.sagepub.com>
Joe Marshall <···@ccs.neu.edu> writes:

> sv0f <····@vanderbilt.edu> writes:
> 
> > In article <············@ccs.neu.edu>, Joe Marshall <···@ccs.neu.edu> 
> > wrote:
> > 
> > >Steven E. Harris <········@raytheon.com> writes:
> > >
> > >> Joe Marshall <···@ccs.neu.edu> writes:
> > >> 
> > >> > Bonus question:  Why is this not a good idea?
> > >> > (Hint:  the accessors are generic functions.)
> > >> 
> > >> Because the chosen naming conflates the specific class defined here
> > >> with generic function names that could be applicable to a broad set of
> > >> classes (that don't need to be related through inheritance)?
> > >
> > >You get the cigar!
> > 
> > And even if they are related by inheritance, because the
> > accessor methods are automatically generated, they will
> > not invoke CALL-NEXT-METHOD.  Therefore, the primary
> > methods of superclasses may inadvertently not be called.
> > 
> > Is this corollary true?
> 
> Yes.
> 
> And if you start using around or before or after methods on the
> superclass, then you'd see it even more.  The subclass would share the
> slot, but there would be two accessors defined for the slot, one that
> used the around method, and one that didn't.  Lot's of fun debugging
> that one!  Likewise if you explicitly called CALL-NEXT-METHOD.

This is all true, but the point of the macro was to make it easier to
declare simple classes in the style of DEFSTRUCT.  Obviously if the macro
does not allow you to specify superclasses (it doesn't), you aren't going 
to be using it for anything besides simple standalone classes.

---
Jock Cooper
http://www.fractal-recursions.com
From: Michael Park
Subject: Re: classes and structs
Date: 
Message-ID: <ff20888b.0305201507.3e43f13@posting.google.com>
Steven E. Harris <········@raytheon.com> wrote in message news:<···············@raytheon.com>...
> Joe Marshall <···@ccs.neu.edu> writes:
> 
> > Bonus question:  Why is this not a good idea?
> > (Hint:  the accessors are generic functions.)
> 
> Because the chosen naming conflates the specific class defined here
> with generic function names that could be applicable to a broad set of
> classes (that don't need to be related through inheritance)?

Can you give examples using Jock's DEFCLASSIFIER?
From: Steven E. Harris
Subject: Re: classes and structs
Date: 
Message-ID: <q67n0hhgoby.fsf@raytheon.com>
···········@whoever.com (Michael Park) writes:

> Can you give examples using Jock's DEFCLASSIFIER?

I'd probably pass "" as the "class" cadr argument to force an empty
conc-name. For examples of /why/ one might want these kinds of names,
perhaps Joe Marshall can chime in.

Most of my applicable experience comes from C++, not CL, but I'm
starting to see how some of the newer generic programming idioms
arising in C++ are even more natural in CL. The most applicable idiom
that comes to mind may have a name, but I don't know it. I'll describe
it until I can refer to it by name.

To provide a common interface to a facility with many potential
implementations, one can first go the abstract interface route�:

struct graph
{
   virtual size_t num_vertices() const = 0;
   virtual size_t num_edges() const = 0;
   // ...
};


class edge_list_graph : public graph
{
public:
   size_t num_vertices() const;
   size_t num_edges() const;
   // ...
};


class vertex_list_graph : public graph
{
public:
   size_t num_vertices() const;
   size_t num_edges() const;
   // ...
};

With these kinds of declarations, one can write graph algorithms in
terms of the graph interface. All possible graph implementations must
derive from the graph base class, though. To integrate existing graph
types into this type hierarchy, one can write an adapting wrapper
type, but all of the function dispatching still must be delayed until
runtime by way of vtable lookups.

More recent C++ template techniques offer a different means to a
similar end: compile-time polymorphism by way of template interfaces
or "concepts." The above example might look more like this:

template <typename Graph>
size_t num_vertices(const Graph&);

template <typename Graph>
size_t num_edges(const Graph&);

struct edge_list_graph
{ /* ... */ };

template <>
size_t num_vertices(const edge_list_graph& g)
{ /* ... */ }

template <>
size_t num_edges(const edge_list_graph& g)
{ /* ... */ }

struct vertex_list_graph
{ /* ... */ };

template <>
size_t num_vertices(const vertex_list_graph& g)
{ /* ... */ }

template <>
size_t num_edges(const vertex_list_graph& g)
{ /* ... */ }

Note that edge_list_graph and vertex_list_graph no longer share an
inheritance hierarchy. Also note that, while not likely possible in
this example, one can specialize these interface functions on built-in
types. The function dispatching is resolved at compile time; no
vtables are needed.

I present all of this C++ just to show that the latter example - using
templates to provide a generic, free-function interface - is the
natural way that CLOS works. When one defines some class "foo" and
prefixes the slot names with "foo-," those slot accessor functions
have lost potential generic applicability. Class "foo" may be one
implementation of a broader concept. Naming the slot accessors with
such narrow focus may forestall discovery of some commonality and
variation in the problem domain.

Mind you, I don't have much experience using these ideas in CLOS. For
now, it's just a transfered intuition that tells me that seeking the
concepts, not the classes, is the better path.


Footnotes: 
� These examples are sketched from the excellent Boost Graph Library,
  or BGL, described at
  <URL:http://www.boost.org/libs/graph/doc/table_of_contents.html>

-- 
Steven E. Harris        :: ········@raytheon.com
Raytheon                :: http://www.raytheon.com
From: Jeff Caldwell
Subject: Re: classes and structs
Date: 
Message-ID: <QjCya.421$bO6.345879@news1.news.adelphia.net>
I first was exposed to this style of template programming in the STL. 
Have you read that Stepanov first worked in functional languages and 
built a large library in Scheme prior to moving first to Ada and then to 
C/C++, where he worked with Stroustrup to add templates, and other 
features, to the language specifically to support what became the STL?

If many C++ template idioms seem natural in Lisp, it may well be because 
  templates and the STL came from a Lisp.

http://www.sgi.com/tech/stl/drdobbs-interview.html


Steven E. Harris wrote:
...

> 
> Most of my applicable experience comes from C++, not CL, but I'm
> starting to see how some of the newer generic programming idioms
> arising in C++ are even more natural in CL. The most applicable idiom
> that comes to mind may have a name, but I don't know it. I'll describe
> it until I can refer to it by name.
From: Steven E. Harris
Subject: Re: classes and structs
Date: 
Message-ID: <q677k8ix6g9.fsf@raytheon.com>
Jeff Caldwell <·····@yahoo.com> writes:

> I first was exposed to this style of template programming in the
> STL.

But even the STL misses this point. Consider Container::begin() or
end() or size(), for example. These are member functions on the
concrete Container template types (such as vector). They could have
been free functions, which would have allowed specializing them for
statically sized arrays. Instead, we see various wrapper classes
trying to cram arrays back into the Container concept.

Perhaps recognizing that pointers are random-access iterators -- and
thus work perfectly well with the algorithms -- is enough. After all,
the containers were not so central to the STL idea as iterators and
algorithms, even if containers enjoy the most use and attention in
practice.

[...]

> If many C++ template idioms seem natural in Lisp, it may well be
> because templates and the STL came from a Lisp.

That would make sense. I was just pointing out that we don't always
encounter ideas first at their source, or at their best
realization. Take lambda in Python.

> http://www.sgi.com/tech/stl/drdobbs-interview.html

Yes, I read this article in 1998, well before I started learning about
CLOS. My big take-away at the time was with iconoclastic Stepanov's
views on object-oriented programming:

  Object-oriented programming aficionados think that everything is an
  object. When I was working on the Ada generic library, I realized
  that this wasn't so. There are things that are objects. Things that
  have state and change their state are objects. And then there are
  things that are not objects. A binary search is not an object. It is
  an algorithm. Moreover, I realized that by decomposing the component
  space into several orthogonal dimensions, we can reduce the number
  of components, and, more importantly, we can provide a conceptual
  framework of how to design things.

It was powerful reassurance for my then-budding doubts about the
sanctity of the OOP Way.

-- 
Steven E. Harris        :: ········@raytheon.com
Raytheon                :: http://www.raytheon.com
From: Steven E. Harris
Subject: Re: classes and structs
Date: 
Message-ID: <q673cj6x69c.fsf@raytheon.com>
Steven E. Harris <········@raytheon.com> writes:

> My big take-away at the time was with iconoclastic Stepanov's views
> on object-oriented programming:
                                        ^---------------------^

s/(iconoclastic) (Stepanov's)/\2 \1/

-- 
Steven E. Harris        :: ········@raytheon.com
Raytheon                :: http://www.raytheon.com
From: Rick
Subject: Re: classes and structs
Date: 
Message-ID: <3ECC58D8.CCD4EC62@yahoo.com>
"Steven E. Harris" wrote:
> 
> Joe Marshall <···@ccs.neu.edu> writes:
> 
> > Bonus question:  Why is this not a good idea?
> > (Hint:  the accessors are generic functions.)
> 
> Because the chosen naming conflates the specific class defined here
> with generic function names that could be applicable to a broad set of
> classes (that don't need to be related through inheritance)?
> 

If you use general generic method names, some other unrelated class may
one day need a generic function of the same name with a different number
of arguments. Which wouldn't be allowed. I think.
From: Joe Marshall
Subject: Re: classes and structs
Date: 
Message-ID: <llwzdt3l.fsf@ccs.neu.edu>
Rick <······@yahoo.com> writes:

> "Steven E. Harris" wrote:
> > 
> > Joe Marshall <···@ccs.neu.edu> writes:
> > 
> > > Bonus question:  Why is this not a good idea?
> > > (Hint:  the accessors are generic functions.)
> > 
> > Because the chosen naming conflates the specific class defined here
> > with generic function names that could be applicable to a broad set of
> > classes (that don't need to be related through inheritance)?
> > 
> 
> If you use general generic method names, some other unrelated class may
> one day need a generic function of the same name with a different number
> of arguments. Which wouldn't be allowed. I think.

It wouldn't.  (Assuming you didn't partition things into separate
packages.)

In either case, it is useful to think about what names the selectors
ought to have and to choose them explicitly.  One project I worked on
had a wrapper for defclass that automagically created selectors.  It
was great until I had to create a class hierarchy with abstract base
classes.  Then you had to know where in the class hierarchy the slot
was defined in order to know its full name.

In another case, it turned out we shouldn't have implemented a
function as a slot, but as something a bit more complicated.  In CLOS,
it's trivial to rename the accessor, but keep the slot name the same
(because it was a persistent object, renaming the slot meant a schema
change).  With the automagic slot accessors, it's impossible.
From: Rob Warnock
Subject: Re: classes and structs
Date: 
Message-ID: <cs2cnXMS276oDU2jXTWc-w@speakeasy.net>
Joe Marshall  <···@ccs.neu.edu> wrote:
+---------------
| Rick <······@yahoo.com> writes:
| > "Steven E. Harris" wrote:
| > > Joe Marshall <···@ccs.neu.edu> writes:
| > > > Bonus question:  Why is this not a good idea?
| > > > (Hint:  the accessors are generic functions.)
| > > Because the chosen naming conflates the specific class defined here
| > > with generic function names that could be applicable to a broad set of
| > > classes (that don't need to be related through inheritance)?
| > 
| > If you use general generic method names, some other unrelated class may
| > one day need a generic function of the same name with a different number
| > of arguments. Which wouldn't be allowed. I think.
| 
| It wouldn't.  (Assuming you didn't partition things into separate packages.)
| 
| In either case, it is useful to think about what names the selectors
| ought to have and to choose them explicitly.
+---------------

Indeed. In fact, I just ran into that situation just the other day, when
without thinking too carefully about it I typed something like this:

	(defclass pool ()
	  ((type  :initarg :type  :accessor type  :initform :generic)
	   (count :initarg :count :accessor count :initform 0)
	   (list  :initarg :list  :accessor list  :initform nil)
	   ;...
	   ))

*OOPS!*  At least CMUCL was kind enough to give me a clear error:

	...[other chatter]...
	COUNT already names an ordinary function or a macro.
	If you want to replace it with a generic function, you should remove
	the existing definition beforehand.

	Restarts:
	  0: [CONTINUE] Discard the existing definition of COUNT.
	  1: [ABORT   ] Return to Top-Level.
	...

And of course, LIST would have gotten me if COUNT hadn't!  ;-}
Now the code reads like so:

	(defclass pool ()
	  ((type  :initarg :type  :accessor pool-type  :initform :generic)
	   (count :initarg :count :accessor pool-count :initform 0)
	   (list  :initarg :list  :accessor pool-list  :initform nil)
	   ;...
	   ))

And, yes, when I subclassed it with a "connection-pool", I had to
continue the "pool-" prefix convention to avoid the same problem
with a slot named "listen".

And what about a a slot named "phase" in a "connection" class?
Or in a "fats" class, slots named "cis" and "trans"? [Aside: For
those interested in nutrition, in this case the problem *isn't*
with the "trans" fats...  ;-}  ;-} ]

In fact, given the *large* number of useful, short, but all-too-common
names which are functions in the COMMON-LISP package, I'm starting to
wonder if it would be a reasonable idea to adopt a convention of picking
a short, non-conflicting conc-name for each major class hierarchy one
defines, and sticking with it throughout for *all* of the slots of
that particular hierarchy. That is, in the "connection-pool" or other
subclasses, using "pool-XXX" as accessors (but *not* "connection-pool-XXX").

Comments?


-Rob

-----
Rob Warnock, PP-ASEL-IA		<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: Thomas F. Burdick
Subject: Re: classes and structs
Date: 
Message-ID: <xcvel2malm2.fsf@famine.OCF.Berkeley.EDU>
····@rpw3.org (Rob Warnock) writes:

> In fact, given the *large* number of useful, short, but all-too-common
> names which are functions in the COMMON-LISP package, I'm starting to
> wonder if it would be a reasonable idea to adopt a convention of picking
> a short, non-conflicting conc-name for each major class hierarchy one
> defines, and sticking with it throughout for *all* of the slots of
> that particular hierarchy. That is, in the "connection-pool" or other
> subclasses, using "pool-XXX" as accessors (but *not* "connection-pool-XXX").
> 
> Comments?

Depending on the domain you're writing for, this can definately come
up.  Rather than use a conc-name, I use the package system.  In this
case, it might not be much of a difference, but it at least feels
nicer to me.  Philosophically, I like it better because it's not a
type name, but a module name.  That is, I put all the classes for one
module in one package.  For example:

  (defpackage :ir ; "internal representation", like for a compiler
    (:use)
    (:export ; ...
       #:variable-name #:symbol #:version ; ...
       ))

  (defpackage #:ir-impl
    (:use #:cl))

  (in-package #:ir-impl)

  ;; ...

  (defclass ir:variable-name ()
    ((ir:symbol :initarg ir:symbol :reader ir:symbol)
     (next-version :initform 0)))

Now in code that uses the IR graph, if you want to get the symbol[*]
for an instance of VARIABLE-NAME, you write (ir:symbol foo).  I might
(and do) have other accessors for slots named SYMBOL in the same file.
They're all named IR:SYMBOL, not IR:FOO-SYMBOL, IR:BAR-SYMBOL, etc.

[*] None of the released versions of CMUCL will complain about
defining a function named CL:SYMBOL, but the code in CVS now has
package locks (yay!) and will (again, yay).

-- 
           /|_     .-----------------------.                        
         ,'  .\  / | No to Imperialist war |                        
     ,--'    _,'   | Wage class war!       |                        
    /       /      `-----------------------'                        
   (   -.  |                               
   |     ) |                               
  (`-.  '--.)                              
   `. )----'                               
From: Thomas A. Russ
Subject: Re: classes and structs
Date: 
Message-ID: <ymiptmampca.fsf@sevak.isi.edu>
Rick <······@yahoo.com> writes:
> 
> If you use general generic method names, some other unrelated class may
> one day need a generic function of the same name with a different number
> of arguments. Which wouldn't be allowed. I think.

That is correct.  But if the classes are sufficiently unrelated, they
may also be in different packages, thus avoiding the problem.  

In fact, it is perhaps a bit unhelpful in the Lisp mindset to talk about
another class needing a generic function of the same name.  Classes
don't have generic functions.  They don't even have methods.  Generic
functions stand on their own, and if seen in that light, then you won't
have any more problems than if you define a class called NODE and then
decide you also need a class called NODE which has different instance
variables.

The point about avoiding all-too-generic names is well-taken for generic
functions as well as classes.

-- 
Thomas A. Russ,  USC/Information Sciences Institute          ···@isi.edu    
From: Franz Kafka
Subject: Re: classes and structs
Date: 
Message-ID: <NUpya.8473$fT7.7791@news01.roc.ny.frontiernet.net>
"Michael Park" <···········@whoever.com> wrote in message
·································@posting.google.com...
> Why aren't classes as convenient to use as structs? Structs define
> default accessors automatically. Structs can also be read and printed.
> Why not classes?

You can write your own print and read methods that
would be much more powerful--more specific to
the class so you can control how the class is printed.

You can be more expressive with accessors--a default method
would not be as easy to implement as it might first seem
because of inheritance issues.

Using MOP you prob. could write default methods--IMHO, I don't
think it would be worth the effort, because in OO programming you
don't want to show too many details.

However, if you want it, it could be done.
From: Barry Margolin
Subject: Re: classes and structs
Date: 
Message-ID: <kAqya.4$Oe6.601@paloalto-snr1.gtei.net>
In article <····························@posting.google.com>,
Michael Park <···········@whoever.com> wrote:
>Why aren't classes as convenient to use as structs? Structs define
>default accessors automatically. Structs can also be read and printed.
>Why not classes?

Classes provide more features and give detailed control to the programmer.
Structures are simpler and do more things automatically, but at the expense
of being less flexible.

-- 
Barry Margolin, ··············@level3.com
Genuity Managed Services, a Level(3) Company, Woburn, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.
From: Frode Vatvedt Fjeld
Subject: Re: classes and structs
Date: 
Message-ID: <2hwugllq6h.fsf@vserver.cs.uit.no>
···········@whoever.com (Michael Park) writes:

> Why aren't classes as convenient to use as structs? Structs define
> default accessors automatically. Structs can also be read and
> printed.  Why not classes?

I don't really know why, but perhaps the presence of slot-value has
something to do with it. If you view (slot-value <object> <slot-name)
to name the accessor, I suppose in some sense it's a cleaner approach
than to generate accessor names by concatenating symbols.

-- 
Frode Vatvedt Fjeld