From: David E. Young
Subject: CLOS idioms
Date: 
Message-ID: <3A06E2C5.EDE98107@nc.rr.com>
Greetings. While porting a Java application to Common Lisp I seem to
have exposed a gap in my CLOS knowledge, and would appreciate some
advice.

A particular Java class I'm porting has overloaded constructors; a
couple have two arguments, one three, another just a single. I've
decided this class should be refactored into a base and two derived
classes, but most of the instance initialization should be handled by
the base class to avoid code replication and allow for possible new
descendants.

Now, I'm in the habit of defining "constructors" for my CLOS classes; in
this scenario I would like the descendant constructors to simply hand
initialization off "to the base" (I know, methods don't belong to
classes, but I'm trying to keep the discussion simple). My first thought
was an initializer method that specialized on the base type and the
various arguments; however, since generic function lambda lists must be
congruent that won't work (recall, the contructor argument lists
differ).

So, I'm wondering if there's a CLOS idiom (or "pattern") for this kind
of situation. I suppose I could name each of the four init methods
differently, and perhaps that approach _is_ the standard idiom. But, I'd
like to ask first. Thanks for the help.

Regards,

--
-----------------------------------------------------------------
David E. Young
Fujitsu Network Communications  (defun real-language? (lang)
(········@computer.org)           (cond ((eql lang 'LISP)
                                          'TRUE)
                                        (t 'FALSE)))
"The fact that ... we still
 live well cannot ease the pain of
 feeling that we no longer live nobly."
  -- John Updike

From: Sunil Mishra
Subject: Re: CLOS idioms
Date: 
Message-ID: <3A070027.8090405@everest.com>
Hi David,

Do &rest and/or &key arguments to the constructor gf (or perhaps 
ordinary function?) not suffice? If not, could you please explain why not?

Sunil

David E. Young wrote:

> Greetings. While porting a Java application to Common Lisp I seem to
> have exposed a gap in my CLOS knowledge, and would appreciate some
> advice.
> 
> A particular Java class I'm porting has overloaded constructors; a
> couple have two arguments, one three, another just a single. I've
> decided this class should be refactored into a base and two derived
> classes, but most of the instance initialization should be handled by
> the base class to avoid code replication and allow for possible new
> descendants.
> 
> Now, I'm in the habit of defining "constructors" for my CLOS classes; in
> this scenario I would like the descendant constructors to simply hand
> initialization off "to the base" (I know, methods don't belong to
> classes, but I'm trying to keep the discussion simple). My first thought
> was an initializer method that specialized on the base type and the
> various arguments; however, since generic function lambda lists must be
> congruent that won't work (recall, the contructor argument lists
> differ).
> 
> So, I'm wondering if there's a CLOS idiom (or "pattern") for this kind
> of situation. I suppose I could name each of the four init methods
> differently, and perhaps that approach _is_ the standard idiom. But, I'd
> like to ask first. Thanks for the help.
> 
> Regards,
> 
> --
> -----------------------------------------------------------------
> David E. Young
> Fujitsu Network Communications  (defun real-language? (lang)
> (········@computer.org)           (cond ((eql lang 'LISP)
>                                           'TRUE)
>                                         (t 'FALSE)))
> "The fact that ... we still
>  live well cannot ease the pain of
>  feeling that we no longer live nobly."
>   -- John Updike
From: David E. Young
Subject: Re: CLOS idioms
Date: 
Message-ID: <3A070C46.313ADBBC@nc.rr.com>
Sunil Mishra wrote:

> Hi David,
>
> Do &rest and/or &key arguments to the constructor gf (or perhaps
> ordinary function?) not suffice? If not, could you please explain why not?
>
> Sunil
>

Hello Sunil. Actually, that's just the solution I decided upon, using an
:after INITIALIZE-INSTANCE and supplying certain keywords that define the
type of initialization requested. When I first considered that approach it
didn't "feel" correct; however, that was probably my conventional OO
background getting in the way. Thanks much for responding.

BTW, have we spoken before? Your name is familiar...

Regards,

--
-----------------------------------------------------------------
David E. Young
Fujitsu Network Communications  (defun real-language? (lang)
(········@computer.org)           (cond ((eql lang 'LISP)
                                          'TRUE)
                                        (t 'FALSE)))
"The fact that ... we still
 live well cannot ease the pain of
 feeling that we no longer live nobly."
  -- John Updike
From: David Bakhash
Subject: Re: CLOS idioms
Date: 
Message-ID: <m3zojcr99f.fsf@cadet.dsl.speakeasy.net>
"David E. Young" <·······@nc.rr.com> writes:

> Hello Sunil. Actually, that's just the solution I decided upon,
> using an :after INITIALIZE-INSTANCE and supplying certain keywords
> that define the type of initialization requested.

This is exactly right.  :after methods on #'INITIALIZE-INSTANCE
usually do the trick, and the nice thing about standard method
combination is that *all* after methods get executed up the hierarchy, 
and in a nice order (least-specific first).  It's a very well
thought-out scheme for whatever extra stuff you want to add to object
creation.

Another thing that people do is to create constructors such as:

#'MAKE-<class-name>

and within those functions, is the call to #'MAKE-INSTANCE.  I'm
actually a big fan of hiding the call to #'MAKE-INSTANCE behind such a 
constructor, even though I also use :after methods heavily.

There's upside in both paradigms, but one of the things I like a lot
about the #'MAKE-<class-name> way is that:

 1) It strongly resemles standard structure creation, which (while
    others may _not_ like that, I do).
 2) It makes it easy to have a single place to put things that would
    normally go in :before, :after, and :around methods, and
 3) For API reasons, it's nicer to wrap the default CLOS constructor
    and specify that people not use the default constructor.  That
    way, if they find that there's no constructor that was ready-made
    for them, then they get the hint that you didn't want them
    instantiating objects of that class.

I'd like to hear other people's opinions, as I'm sure they'll differ.
Please don't forget to say _why_.  Otherwise, we learn nothing.

dave
From: Marco Antoniotti
Subject: Re: CLOS idioms
Date: 
Message-ID: <y6csnp323gf.fsf@octagon.mrl.nyu.edu>
David Bakhash <·····@alum.mit.edu> writes:

> "David E. Young" <·······@nc.rr.com> writes:
> 
> > Hello Sunil. Actually, that's just the solution I decided upon,
> > using an :after INITIALIZE-INSTANCE and supplying certain keywords
> > that define the type of initialization requested.
> 
> This is exactly right.  :after methods on #'INITIALIZE-INSTANCE
> usually do the trick, and the nice thing about standard method
> combination is that *all* after methods get executed up the hierarchy, 
> and in a nice order (least-specific first).  It's a very well
> thought-out scheme for whatever extra stuff you want to add to object
> creation.
> 
> Another thing that people do is to create constructors such as:
> 
> #'MAKE-<class-name>

I do the same.  I also tend to use a CLIMism

	make-<class-name>
	make-<class-name>*

The first one takes "bundled" parameters while the second takes
"spread" ones.  I do not have a handy example at hand, but think of
the case

	public class Line {
           public void draw(Point x, Point y);
           public void draw(int x1, int x2, int y1, int y2);
        }

I do the following

	(defmethod draw ((l line) x y)) ; You could specialize on all args.
	(defmethod draw* ((l line) x1 x2 x3 x4))

I like this CLIMism.  And I believe it works well.

> and within those functions, is the call to #'MAKE-INSTANCE.  I'm
> actually a big fan of hiding the call to #'MAKE-INSTANCE behind such a 
> constructor, even though I also use :after methods heavily.
> 
> There's upside in both paradigms, but one of the things I like a lot
> about the #'MAKE-<class-name> way is that:
> 
>  1) It strongly resemles standard structure creation, which (while
>     others may _not_ like that, I do).
>  2) It makes it easy to have a single place to put things that would
>     normally go in :before, :after, and :around methods, and
>  3) For API reasons, it's nicer to wrap the default CLOS constructor
>     and specify that people not use the default constructor.  That
>     way, if they find that there's no constructor that was ready-made
>     for them, then they get the hint that you didn't want them
>     instantiating objects of that class.
> 
> I'd like to hear other people's opinions, as I'm sure they'll differ.
> Please don't forget to say _why_.  Otherwise, we learn nothing.

Sorry, I have no reasons for doing what I do (excpet reading Sonya
Keene's book).

Cheers

Marco

-- 
Marco Antoniotti =============================================================
NYU Bioinformatics Group			 tel. +1 - 212 - 998 3488
719 Broadway 12th Floor                          fax  +1 - 212 - 995 4122
New York, NY 10003, USA				 http://galt.mrl.nyu.edu/valis
             Like DNA, such a language [Lisp] does not go out of style.
			      Paul Graham, ANSI Common Lisp
From: Kent M Pitman
Subject: Re: CLOS idioms
Date: 
Message-ID: <sfwzojbzr1o.fsf@world.std.com>
David Bakhash <·····@alum.mit.edu> writes:

> Another thing that people do is to create constructors such as:
> 
> #'MAKE-<class-name>

Doesn't this involve a lot of use of excess use of vertical bars?
Why not just make the constructor be MAKE-<class-name> ?

;-)

Seriously, it seems a recent passion of people to refer to function
names with #' in front of them.  I think this is wrong.  When you say
"a call to #'MAKE-FOO", the only possible reason for this would be
that you fear that saying "a call to MAKE-FOO" will somehow imply a
special or lexical variable called MAKE-FOO.  I think people never
assume this.  They might if you used the word "funcall" instead of "call",
but "call" is not an operator and it refers to a compound form whose car
is the indicated item, in this case MAKE-FOO, as in: (MAKE-FOO ...)
Since the car is not #'MAKE-FOO, and it would be an error for it to be
so, I believe people should just be using the simpler notation.

I and others spent years of our lives trying to make Lisp be not only
something you could write in code, but something you could talk about
out loud without sounding like a nerd.  (This is, though I will not
belabor it here, one of the reasons I take the position I do on case
sensitivity: people do not vocalize case in conversation, and since I
want people to converse about code without saying "I call
all-uppercase KILL" or "No, you have to call call uppercase-initial
KILL" because that sounds dorky as hell, I prefer a case-folding
reader.)

This is also why I don't favor indentation-oriented code.  When you speak
a language (not to Dragon Naturally Speaking or some such engine, but to
a person), there is no indentation.  When you jot something down on paper,
not graph paper but napkins in restaurants over dinner, the language should
be forgiving.

And I and others before and with me wasted a lot of words creating
precise names for things that we could just as well have called conses
but we choose to call forms or expressions or calls, each with subtly
different meanings exactly so that the words would, as they say, flow
trippingly off the tongue.

Many exist for routine patterns like property lists and association
lists and other things that are routinely used, so that we can talk
about them in high level terms, free of syntax, even with others who
use different dialects.  The function CAR exists in Lisp and Scheme and
people can talk about it without caring, but if you write it or enunciate
it as #'CAR, you are locking out a whole community of Scheme programmers
needlessly and contributing to their needless fear that CL forces this
extra notation on you.

If you look at the notation for CLHS, you'll see that I worked a lot
to make little accomodations to be able to say "an after method"
rather than "a :after method" or "an :after method" so we all wouldn't
fight over whether to pronounce the colon.  

#' is not part of a function name.  #' and the (function ...) notation is
a coercion operator that says "The syntactic position that you find this
name in suggests that this should be a variable, but I wish to extract
the value from the function namespace instead."  FUNCALL, while not a 
syntactic mechanism but a simple function, has approximately the opposite
effect saying "The syntactic position I was going to write the function to
call in would have forced its evaluation in the function namespace, but I
wish to do a variable namespace evaluation instead, so I've used FUNCALL to
move the name over into a place where that will happen naturally."  But
the whole purpose of both of these "syntactic coercion" operators, is to
allow you to most of the time use both sets of names in an unambiguous 
way simply by noting the "expected context" and having the right thing
happen.  When you use #' in a sentence like "I never use the function #'CAR."
you are effectively denyhing that functions are named in the function
namespace and asserting that it is unpredictable whether the <something>
in the phrase "the function <something>" is found in the function or variable
namespace.  I think that's needless.
From: David Bakhash
Subject: Re: CLOS idioms
Date: 
Message-ID: <m37l6fgkqb.fsf@cadet.dsl.speakeasy.net>
kent,

we all have different ways of expressing ourselves.  I like to refer
to symbols in email and newsgroup messages in uppercase, and like to
put #' before things that are functions, and *'s before and after
globals, +'s around constants, etc.  It's just the way I write, and
it's expressive, as it conveys more information about what I'm trying
to say.  I know that in the case where I used it in the referenced
message it was obvious.  But it's force of habit with me, and I don't
think about it too much.  I agree that it's verbose, but not
necessarily to the point where it deserves serious review.

dave
From: Paolo Amoroso
Subject: Re: CLOS idioms
Date: 
Message-ID: <DywIOpzrL+4CXGn0Yf50zAKYrMTX@4ax.com>
On Tue, 07 Nov 2000 07:49:27 GMT, David Bakhash <·····@alum.mit.edu> wrote:

> Another thing that people do is to create constructors such as:
> 
> #'MAKE-<class-name>
> 
> and within those functions, is the call to #'MAKE-INSTANCE.  I'm
> actually a big fan of hiding the call to #'MAKE-INSTANCE behind such a 
> constructor, even though I also use :after methods heavily.
[...]
> I'd like to hear other people's opinions, as I'm sure they'll differ.

Sonya Keene ("Object-Oriented Programming in Common Lisp - A Programmer's
Guide to CLOS", Addison-Wesley, 1989; section 9.6 "Constructors", page 163)
recommends using constructors because they:

- add a valuable level of abstraction between the client and the
  implementation
- can use the full power of Common Lisp argument-processing
- conceal the implementation of objects

The following paper:

  "On the design of encapsulated CLOS applications"
  Charlotte Pii, Kjeld Larsen
  Journal of Object-Oriented Programming, November-December 1994, page 34

suggests the use of constructors, especially in large systems, as a way of
coping with the difficulties of initializing inherited slots.


Paolo
-- 
EncyCMUCLopedia * Extensive collection of CMU Common Lisp documentation
http://cvs2.cons.org:8000/cmucl/doc/EncyCMUCLopedia/
From: David Bakhash
Subject: Re: CLOS idioms
Date: 
Message-ID: <m3zojbf5ze.fsf@cadet.dsl.speakeasy.net>
Paolo Amoroso <·······@mclink.it> writes:

> ...suggests the use of constructors, especially in large systems, as
> a way of coping with the difficulties of initializing inherited
> slots.

Yes.  This is where you can place functionality in :after methods of
#'INITIALIZE-INSTANCE or put it in the constructor.  I sometimes do
both.  Don't know if it's good style, but I think the :after method
is just neat.

dave
From: Robert Monfera
Subject: Re: CLOS idioms
Date: 
Message-ID: <3A0B7F6F.168FEDA3@fisec.com>
Paolo Amoroso wrote:

> Sonya Keene ("Object-Oriented Programming in Common Lisp - A
> Programmer's Guide to CLOS", Addison-Wesley, 1989; section 9.6
> "Constructors", page 163) recommends using constructors because they:
> 
> - add a valuable level of abstraction between the client and the
>   implementation
> - can use the full power of Common Lisp argument-processing
> - conceal the implementation of objects

This may be true, but these values are questionable.  Let's take two
meanings of "client and the implementation":

A. Client and implementation are within the same module:
This is admittedly a weird meaning, for example because classes aren't
considered modules in Lisp (see the frequent use of multi-methods
etc.).  In any case, of what value would be the "valuable level of
abstraction" and "concealment"?  You gain nothing, unless the model is
so simple you might as well use some other data types easily like
structs.  Just use make-instance inside your module, you don't lose
anything.  As for "full power of argument processing": I don't see how
that helps.  If you have 1-3 args, who cares about the keywords.  If
there are more, required arguments would be a nightmare on their own
right.

B. Client and implementation are separate modules (maybe client is not 
   even in Lisp)

OK, if it is easier to give make-foo to your C++ client for simpliciy or
encapsulation, so be it.  But then we talk about a thin package for
interfacing.  You can still use all the CLOS power internally -
make-instance, change-class etc.  Presumably the core logic is more
substantial than a thin interface package, so the latter should not
drive the former?

> The following paper:
> 
>   "On the design of encapsulated CLOS applications"
>   Charlotte Pii, Kjeld Larsen
>   Journal of Object-Oriented Programming, November-December 1994
> 
> suggests the use of constructors, especially in large systems, as a way
> of coping with the difficulties of initializing inherited slots.

I haven't read the paper.  What are these "difficulties"?  I think the
large Lisp systems especially benefit more from _not_ using
constructors.

Robert
From: Raymond Laning
Subject: Re: CLOS idioms
Date: 
Message-ID: <3A08BF4E.6927FE40@west.raytheon.com>
David Bakhash wrote:
> 
> "David E. Young" <·······@nc.rr.com> writes:
<snip>
> Another thing that people do is to create constructors such as:
> 
> #'MAKE-<class-name>
> 
> and within those functions, is the call to #'MAKE-INSTANCE.  I'm
<snip>

Defining constructors like this is often a good thing, but generally
only if the class is a terminal one, i.e., one with no subclasses. 
Someone trying to inherit this class would not obtain the desired
initializations unless he duplicated the code in make-<class-name> in
his initializing function, which would pretty much defeat the notion of
modularity and code reuse.
From: David Bakhash
Subject: Re: CLOS idioms
Date: 
Message-ID: <m3snp3f5ug.fsf@cadet.dsl.speakeasy.net>
Raymond Laning <········@west.raytheon.com> writes:

> Defining constructors like this is often a good thing, but generally
> only if the class is a terminal one, i.e., one with no subclasses.
> Someone trying to inherit this class would not obtain the desired
> initializations unless he duplicated the code in make-<class-name>
> in his initializing function, which would pretty much defeat the
> notion of modularity and code reuse.

This is an excellent point, and I think most people (including myself) 
would agree that you wouldn't tend to define #'MAKE-<class-name>'s on
classes you didn't want to directly make instances on.  That's why in
another post (or posts) I said I often use both this technique and the 
:after methods on #'INITIALIZE-INSTANCE together.  Again, that's just
style.

dave
From: Robert Monfera
Subject: Re: CLOS idioms
Date: 
Message-ID: <3A0B8106.E6C962A3@fisec.com>
David Bakhash wrote:

> There's upside in both paradigms, but one of the things I like a lot
> about the #'MAKE-<class-name> way is that:
> 
>  1) It strongly resemles standard structure creation, which (while
>     others may _not_ like that, I do).

This suggests that constructors do a fine job where structs do a fine
job, but nothing more. 

>  2) It makes it easy to have a single place to put things that would
>     normally go in :before, :after, and :around methods, and

It is a disadvantage and a common pitfall, as you and others later point
out.

>  3) For API reasons, it's nicer to wrap the default CLOS constructor
>     and specify that people not use the default constructor.  That
>     way, if they find that there's no constructor that was ready-made
>     for them, then they get the hint that you didn't want them
>     instantiating objects of that class.

Wrap it or not, if you export the symbol (to allow dispatch), others can
instantiate it.  The real question is, why should we not let them use
make-instance in the first place?  It's not addressed in #3.
 
> I'd like to hear other people's opinions, as I'm sure they'll differ.
> Please don't forget to say _why_.  Otherwise, we learn nothing.

I just posted a longer list of points for Dave.

Robert
From: Robert Monfera
Subject: Re: CLOS idioms
Date: 
Message-ID: <3A0B76DF.C825217A@fisec.com>
"David E. Young" wrote:

> Now, I'm in the habit of defining "constructors" for my CLOS classes;
> in this scenario I would like the descendant constructors to simply
> hand initialization off "to the base" (I know, methods don't belong to
> classes, but I'm trying to keep the discussion simple). My first
> thought
> was an initializer method that specialized on the base type and the
> various arguments; however, since generic function lambda lists must be
> congruent that won't work (recall, the contructor argument lists
> differ).

As others probably recommended, you can use the standard make-instance
mechanism and its surrounding (after methods on them or
initialize-instance or shared-initialize).  Make-instance is using
keyword arguments, and &allow-other-keys does a good job of not having
to deal with irrelevant keyword arguments in ancilliary (before, after,
around) methods.

Without more information, I prefer make-instance over constructors like
make-frob, for these two groups of reasons:

Abstraction:
= keyword arguments give more flexibility - as you keep adding initargs,
  old ways of calling make-instance would work, if there's a default
= there are often multiple ways of initializing objects
    (e.g., you pass either interest rate _or_ interest payment)
= helps avoid pitfalls (anything more than a call to make-instance
  in make-frob risks jeopardize the benefits of inheritance)
= even make-frob would not make it possible _not_ to use an after method
  on make-instance&co, for the reason above
= exporting make-frob is no different from exporting the class name
  for the purpose of instantiation (handy for making dispatching 
  on object class available, too)
= if you export frob to enable dispatching, you can't prohibit people 
  from intuitively, but mistakenly using (make-instance 'frob) anyway
= there is a direct relationship between 
  (make-instance 'frob) and (defmethod ((foo frob)...)...) - while 
  make-frob (or make-frob*?) necessitates naming conventions
= object-oriented tools would work more naturally with make-instance
  than make-frob

Efficiency (development and run-time):
= least resistance (no costructor method to write and maintain)
= make-frob is not more efficient, even if it has required arguments
  rather than keyword args - it has to call make-instance, right?
= make-frob would add a level of indirection (one more function call),
  so it's slower

There are some advantages to make-frob, too:
- make-frob could use non-keyword arguments (I don't know when it would
  be useful, but maybe a proponent of make-frob would chime in)
- you can put in a breakpoint or call-count for make-frob (can be done
  with an after-method on make-instance too)
- makes it easier to do a :who-calls reference tracking (maybe we need
  need :who-instantiates?) - it's a minor question of convenience, as
  we would need :who-specializes-methods-on for both ways
- you retain flexibility in your protocol to change to an alternative
  representation like structs (which could be problematic anyway, as
  your new make-frob will have to use keyword args, while the old one
  maybe used required args)

Advantages for make-frob are only perceived ones (non-trivial models
won't let you enjoy the last two benefits, as there is dispatching and
multiple inheritance and other CLOS-only things), and the widespread
practice of using make-frob is coming from struct reflexes and the
simplicity of textbook examples.

And if we justify make-frob, we have to consider:
  initialize-frob (sugar coating on initialize-instance)
  reinitialize-frob       <-> (reinitialize-instance)
  modify-frob             <-> (reinitialize-instance)
  change-frob-to-fuk      <-> (change-class a-frob 'fuk)
  change-fuk-to-frob      <-> (change-class a-fuk 'frob)
  make-frob*              <-> (make-instance 'frob with other arguments)
  frob-p                  <-> (typep o 'frob)
  (cond ((frob-p o)..)..) <-> (defun foo ((o frob)..)..)
  
etc.

So how could we exactly justify the implementation of an ad-hoc sugar
coating layer poorly bolted atop of CLOS, which is a fine example of
protocol design?  Why should we pollute our symbol space with redundant,
glued names?  Let's not program CLOS in struct style.

Robert