[Prev][Next][Index][Thread]

Re: Need help with Class-Allocated Slots



On Thu, 29 Jun 2000, Dustin Voss wrote:
> In article 
> <Pine.GSO.3.96.1000629115446.4116H-100000@tardis.tardis.ed.ac.uk>, Hugh 
> Greene <q@tardis.ed.ac.uk> wrote:
> 
> > On Wed, 28 Jun 2000, Dustin Voss wrote:
> > > In article <m3zoo8p02k.fsf@soma.andreas.org>, Andreas Bogk 
> > > <andreas@andreas.org> wrote:
> > > 
> > > > "Scott McKay" <swm@mediaone.net> writes:
> > > > 
> > > > > During the design of Dylan, I proposed that class slots be
> > > > > accessible by calling the accessor on the class object itself, but
> > > 
> > > I'm actually surprised this is even being considered.  The idea that 
> > > class slots belong to the class itself is incorrect ...
> > 
> > Good exposition but I have to disagree :-)
> 
> Thanks!  I did what could to shine the light of truth on the sinners in 
> Gamorrah...yup...

Said light being shone from the watch towers on the city walls of Sodom,
of course ;-P

> > IMHO, as a philosophical point, I'd say that, as long as an idea is
> > consistent in itself and its context, it's not "incorrect"; it may well 
> > be "useless"  or "unpopular", though ;-)  In particular, the JOOP
> > article I quoted yesterday specifically wanted "my" behaviour from
> > languages instead of "yours".
> 
> "The difference between theory and practice is that in theory, there is 
> no difference, but in practice, there is."

Yes; but see below for some "in practice".

> Practical is nice.  But Dylan already handles methods and singletons 
> differently than Java, why not this too?  And, actually, I wonder why 
> the author of the JOOP article specifically wanted class slots to have 
> that syntax.  Did the article say?

The author's reasons "[were] twofold:

 - To remove the use of global variables.  Reducing the need for global
   data variables and methods implies also that the possibility of
   conflicts due to name clashes is decreased.

 - To remove the need for so-called utility classes, i.e., classes with
   only one instance."

I don't think either of these reasons work in Dylan, because we can have
global functions (instead of utility classes) scoped by modules (instead
of classes).

However, here's a more concrete reason, based on my programming experience
in Dylan, for wanting class slots to be accessible without instances.
Every once in a while you have a class for which creation of instances may
allocate some resources "elsewhere" (e.g., database connections, Win32 GUI
resources, etc.) and this allocation may be expensive.  If you have to
create an instance to access a class slot, this may be unacceptable.

Yes, you can have a compiler which recognises and optimises some pattern
for "faking" class-accessible class slots, as you say below.  In fact, you
could have macros wrapping up these paterns (and even effectively replace
\class-definer; though making each-subclass slots efficient would be
hard, and O(1) very hard, I think).  However, one of the great things
about the Dylan language is how much it does for you, and this is
something else I'd like it to do :-)  Let me see if I can address your
reasons against it ...

> One reason could be that it seems more intuitive to those from a 
> C++/Java background.  

That's *not* my reason! :-)

> ... But as I said,
> 
> > > It's really the same principle as Dylan's singletons.  You can make 
> > > as many instances of a singleton as you like.  It's just that all 
> > > those instances refer to the same object.  ...

I assume you mean the "Singleton class" pattern implemented in Dylan,
rather than the "singleton()" type constructor.  If so, that's something
you can do in C++ and Java, too.  But although there's definitely
similarity, it's not similar enough in some cases, as I explained above:
you may have to pay an unacceptable cost to get at the class state, if you
don't already have an instance to hand.

> Since I *do* come from a C++ background, both threw me.  But once I 
> figured out the rationale, it made perfect sense.  Anyway, if we allow 
> class slots to 'be' part of the class itself, we should similarly allow 
> all slots of a singleton class to be 'part of' the class itself (i.e. 
> treat all of a singleton's slots like class slots) to prevent mismatched 
> concepts.

I disagree (I think -- I'm not sure I understand you here).  You want
class slots in addition to instance slots when you want some state to be
the same for all instances of a class and some to be different.  You want
the Singleton class construction pattern when you only ever want one
instance of a class, in which case the instance/class slot distinction is
irrelevant.  (Unless you want subclasses of your Singleton class; in that
case class slots could still be useful but each-subclass would be
useless.) 

> > > Each class is an instance of <class>.  Conceptually, the lines
> > > 
> > > -------------------------------------
> > > <my-class>.my-class-slot;
> > > my-class-slot-getter (<my-class>);
> > > -------------------------------------
> > > 
> > > imply that <my-class> has a slot called my-class-slot.  But it doesn't! 
> > >  
> > > <my-class> is an instance of <class>, not a sub-class of <class>.  ...
> > 
> > You're right here.  In terms of Dylan's half-hidden meta-object protocol
> > (MOP), this proposal is in effect allowing you to create subclasses of
> > <class>.  (Simplistically, one new subclass for each such instance of
> > <class>.)  We'd presumably still want to keep <class> as a sealed class,
> > so there'd have to be some "magic" here.  However, there's already 
> > "magic" involved in creating things like limited types ...
> 
> Well, let's keep things like that to a minimum.  I'm more comfortable 
> with dot syntax for class slots as "syntactic sugar" than as "how the 
> language actually works", if you take my meaning.

I'm not sure I do know exactly what you mean, but I can agree with
avoiding magic and hackery as much as possible :-)  OTOH, Dylan already
allows some (conceptually pretty clean) hackery for efficiency's sake,
which is one of its major goals.

Now that I think about it, though, it might actually work to make <class>
an open abstract (instantiable? primary?) class (nevertheless containing
whatever slots the implementation needs, though not exported).  There
could be a sealed concrete subclass called, say <simple-class>, adding
nothing other than sealing and "concretion" (if that's a word), and this
is the class to which "make(<class>, ...)" would "down-delegate".

Then any invocation of \class-definer which contained "class" or
"each-subclass" slots would create new instances or subclasses of <class>.
(I *think* I have the details figured out -- I can post them if you like.)

However, the above would be unacceptable if it made Dylan too much more
inefficient.  Any real Dylan implementation gurus care to analyse that
possibility?  I suppose someone will, if I write this up as a language
extension proposal ... :-)

> ... I really don't like messing with standards. Sure, it's not handed
> down from above, but the authors had sound theoretical reasons for
> writing it they way they did: 

This is a sufficiently radical change that I wouldn't want to just "mess"
with the standard.  I'd at least put it through the language
change proposal process and possibly try to open up a "Dylan 2" standard
-- many people have had other, more radical ideas :-)

As for "sound theoretical reasons", Scott McKay just recently said that
"[David] Moon didn't like it because it confuses class vs. instance."  I
don't think it does, personally (or at least, I can see a model where it
doesn't -- there might be others where it does).

> 1) If you think it through, like I did, it reinforces the concept that a 
> class really is just a plain-jane instance of <class>, like any instance 
> of any variable.  Adding class-accessible class slots makes a <class> 
> special...

Right, but maybe we can open up the MOP a bit as I suggested above, so
that it needn't be special.  OTOH, even if we don't, doing "MOP magic" for
efficiency and convenience *does* fit with Dylan's philosophy.  Limited
types are *very* useful and quite intuitive; but you can't (yet) write
some of your own (e.g., limited(<binary-tree>, of: <byte-string>)) and
when you start to think about how to implement them, it does get quite
hairy.

> 2) ...and special cases should be kept to a minimum.

Yes, we're just debating where that minimum should lie ;-)  (And whether
this really is a special case.)

> But again, a compiler that recognizes the idiom and optimizes it is okay 
> by me, but it shouldn't be in the standard.

This on its own doesn't feel like a good argument to me, because you could
create a similar idiom to implement the current state of affairs, which is
in the standard (and which you're defending).  (I acknowledge that this
isn't your only argument, though.)


BTW, I hope all the above comes across in the spirit of constructive
debate, not flamage.  Also, all IMHO, and I may change my mind :-)

Hugh




Follow-Ups: References: