From: Andrew Cooke
Subject: Newbie Q: Methods & Packages
Date: 
Message-ID: <7qob9h$7at$1@nnrp1.deja.com>
Hi,

I suspect I already know the answer to this, but coming from less
dynamic languages am unwilling to trust it without confirmation :)

I have an application which I would like to spread over several packages
(not being used to multimethods I feel happier grouping methods with
classes inside packages, although one package may hold several related
classes - is this normal practice?).  The classes and main methods will
be exported (declared external).

My question is - will method chaining work correctly across packages?

For example, I might have (all external):

package animals:
class animal
class food
method eat(animal, food)
method kill(food)

package Cows:
class Cow(animal)
class Grass(food)
method eat(cow, grass)
method kill(grass)

Now if eat(a-cow, some-grass) is called, and subsequently calls the more
general eat(animal, food), which in turn calls kill(food), will
kill(grass) be called first (being the most specific method)?  Will this
happen even if the call is from an intermediate method that is not
exported?  What do I need to add to the files so that the two packages
know of each other?  Is (use-package "animals") in cows and (use-package
"cows") in animals sufficient?  Will this compile ok (containing
circular references)?

Thanks,
Andrew
http://www.andrewcooke.free-online.co.uk/index.html


Sent via Deja.com http://www.deja.com/
Share what you know. Learn what you don't.

From: Howard R. Stearns
Subject: Re: Newbie Q: Methods & Packages
Date: 
Message-ID: <37D013F2.600E3525@elwood.com>
I realize that you may know some of this, but it might help to take
another look at it in trying to see how everything hangs together.

Here are five separate things:

1. Classes are real objects just like any other piece of data in Lisp,
numbers, characters, functions, etc.  Classes happen to have a name. 
The class-name of a class is a piece of Lisp data, which is of type
SYMBOL.  That is:
   (class-name (class-of (class-name (class-of (make-instance 'cow)))))
=> SYMBOL.

Another property of classes (besides their name) is that they can refer
to other class objects.  Each class object has an ordered list of other
class objects called its class-precedence-list.

2. Generic-functions are real objects just like any other piece of data
in Lisp.  Generic functions happen to have a name.  The
generic-function-name of a generic function is a piece of Lisp data,
which is of type SYMBOL.  (Usually.  Just humor me.)

Another property of generic-functions is that they can refer to other
kinds of objects called methods.  Methods do not have a name
in-and-of-themselves.  When a generic-function is called, the
class-precedence-list of each required argument is examined, and the
results are used to determine which methods belonging to the generic
function are applicable, and how they should be ordered.  The definition
of the generic-function may effect this.  The definitions of individual
methods determine whether one or more of the applicable methods is
actually run.

<Nothing about any of the above has anything directly to do with
packages.>

3. Symbols are real objects just like any other piece of data in Lisp. 
Symbols have a name, which is a string object, and a package, which is a
package object.  To completely identify a symbol, you need to specify
both the name and the package.  For any given symbol, there is only one
symbol with a given name and package.  (I'm glossing over a lot here. 
Again, just humor me.)

4. The Lisp top-level evaluator, and the Lisp file compiler, both do not
read text!  The lisp reader reads characters from a data stream and
creates Lisp objects -- in particular, lists of symbols and some other
literal data.  The evaluator and compiler operate on the lists of
symbols and stuff, and not directly on characters or strings.  For
example, the compiler doesn't care what package some symbol naming a
generic function is in.  It just arranges for a a runtime call of some
particular generic function, named by some symbol.  It PRESERVES the
package information, but it doesn't USE it.  The compiler is only
interested in the IDENTITY (eq-ness) of symbols.

5. Files being compiled by the file compiler can contain characters
arranged in strings that will be read as symbols in any package.  That
is, you can mix different symbols (names) in code within the same file. 
Think about how this relates to the above.

I would suggest that until you are very familiar with this, you keep
everything in the same package.  When you do start working with multiple
packages, you need to be clear that they are really about the identity
(eq-ness) of different symbols, and not directly about anything related
to classes or generic functions.

Also, although you didn't ask about it, I would recommend that when you
first start working with different packages, you should pretend that 5
isn't true.  Keep everything in a file in the same package.  Ideally,
only after you feel you understand "file-compiler literals" (another
subject altogether) should you start to explore mixing different
packages in the same file.
From: Tim Bradshaw
Subject: Re: Newbie Q: Methods & Packages
Date: 
Message-ID: <ey3so4w3ydz.fsf@lostwithiel.tfeb.org>
* Andrew Cooke wrote:
> Now if eat(a-cow, some-grass) is called, and subsequently calls the more
> general eat(animal, food), which in turn calls kill(food), will
> kill(grass) be called first (being the most specific method)?  Will this
> happen even if the call is from an intermediate method that is not
> exported?  

Remember that you don't get the choice of exporting some method or
not.  You export *names* -- symbols, which in your case will be
generic function names I guess -- not methods.

And the answer is, yes, so long as the names of the functions all
resolve to the same symbol (ie (EQ COW::EAT ANIMAL::EAT) is true) then
you are OK.

> What do I need to add to the files so that the two packages
> know of each other?  Is (use-package "animals") in cows and (use-package
> "cows") in animals sufficient?  Will this compile ok (containing
> circular references)?

I'd be surprised if this was the right way of doing it -- circular
USE-PACKAGEs are unlikely to be a good idea I think.

What I'd do is have some protocol -- set of generic functions really,
and perhaps some class definitions -- and have a package which exports
those symbols and defines the relevant generic functions, which I'd
then use in my sub-packages.

So you might have the EAT-KILL package which would define the EAT and
KILL gfs, and perhaps the ANIMAL class, and export those symbols.

But that's just what I'd do, others probably differ.

--tim
From: Thomas A. Russ
Subject: Re: Newbie Q: Methods & Packages
Date: 
Message-ID: <ymiaer3tyr0.fsf@sevak.isi.edu>
Andrew Cooke <······@andrewcooke.free-online.co.uk> writes:

> Hi,
> 
> I suspect I already know the answer to this, but coming from less
> dynamic languages am unwilling to trust it without confirmation :)
> 
> I have an application which I would like to spread over several packages
> (not being used to multimethods I feel happier grouping methods with
> classes inside packages, although one package may hold several related
> classes - is this normal practice?).  The classes and main methods will
> be exported (declared external).

Generally the way Common Lisp applications are organized is with a
single package per application.  That is because packages define
namespaces and mappings between strings and symbols.

  Digression: OK, some of them also define separate internal packages,
     and really large applications will have separate packages for
     each main functional unit.

> My question is - will method chaining work correctly across packages?

Not the way you expect.  That is because each package defines its own
namespace.  In the examples below, there is a method called ANIMALS::EAT
and another one called COWS::EAT.  These methods are not the same,
because they have different names -- each name is a different symbol, so
the names are different.  In fact, if you were to try to use both
packages in a third package you would end up with a name conflict,
because the Lisp system would not know which symbol the string "EAT" was
supposed to map to.

> For example, I might have (all external):
> 
> package animals:
> class animal
> class food
> method eat(animal, food)
> method kill(food)
> 
> package Cows:
> class Cow(animal)
> class Grass(food)
> method eat(cow, grass)
> method kill(grass)
> 
> Now if eat(a-cow, some-grass) is called, and subsequently calls the more
> general eat(animal, food), which in turn calls kill(food), will
> kill(grass) be called first (being the most specific method)?  

Not if you are using (CALL-NEXT-METHOD), since one method is not more
specific than the other.  They are different methods since they have
different NAMES.  By putting the symbols into different packages you
make the names different.  As far as the lisp system is concerned, the
names

	ANIMALS::EAT  and  COWS::EAT

are no more similar than

        EAT  and   CONSUME

They are separate symbols, and the fact that the symbol-name of symbols
in different packages are the same is really a coincidence, but one that
can lead human readers astray, especially when looked at without
including the package qualifiers.

> Will this
> happen even if the call is from an intermediate method that is not
> exported?

If all of the names were in the same package, then you would get the
effect that you expect.

>  What do I need to add to the files so that the two packages
> know of each other?  Is (use-package "animals") in cows and (use-package
> "cows") in animals sufficient?  Will this compile ok (containing
> circular references)?

No.  It will cause problems because of the ambiguity.  Packages are
designed to partition namespaces.  In other words, you would use them to
allow independent pieces of software to refer to the same name without
coming into conflict with each other.

In your case, you would want to have a single package for the entire
application.

As far as structuring things, you can easily distribute the class
definitions and methods into separate files in any way that you wish.
You could use the organization that you have outlined above for files
which are all in the same package.

You could also adopt an alternate organization, one of which would be:

File: classes.lisp
  class animal
  class food
  class Cow(animal)
  class Grass(food)

File: lunch.lisp
  method eat(animal, food)
  method eat(cow, grass)
  
File: violence.lisp
  method kill(food)
  method kill(grass)

or any other organization.  Generally the only requirement imposed by
lisp itself is that class definitions need to be seen by the compiler
or evaluator before any methods are defined that refer to those classes.

----

One final note.  It is possible to structure things so that they will
work, but it will mean aligning your package hierarchy with the class
hierarchy and making sure the right things get exported.  It will cause
a lot of worry, and not really be worth it.  Essentially what you would
need to do is to make sure the COWS package imported (explicitly via
IMPORT or implicitly via USE) the relevant symbols from the ANIMALS
package.  That way there would be only one ANIMAL, FOOD, EAT and KILL
symbol that belongs to the ANIMAL package, but is also refered to in the
COWS package.  But then, the COWS package would either have to re-export
all of the imported symbols, or else anyone wanting convenient access to
the symbols would need to import from or use multiple packages.  As you
see, this begins to get messy.  The reason this is messy is that
packages are not designed to do what you are trying to do.

Packages in Lisp are meant to separate collections of lisp code that are
not expected to interact heavily with each other.  It isn't an access
control mechanism.  It isn't designed to make parts of the code hidden,
since any symbol, exported or not, can be accessed from any other
package, just by providing the appropriate package qualifier, and using
two colons (::) instead of just the one you would need for exported
symbols.


-- 
Thomas A. Russ,  USC/Information Sciences Institute          ···@isi.edu    
From: Andrew Cooke
Subject: Re: Newbie Q: Methods & Packages
Date: 
Message-ID: <7qs09n$nrs$1@nnrp1.deja.com>
After reading all the replies I now have my project sorted into three
nice packages and one uberpackage that ties them all together - very
nice!

Two small related questions:

- first, there doesn't seem to be anything in the package system that
decides which namespace (function, variable, whatever - I remember
something saying there were 7) within a particular package a symbol
refers to.  Does that mean that if I have a constant and a function with
the same name (it's OK, I've read a Lisp style guide and I have some
common sense, but out of curiousity...) both are visible if declared
external?  Is there no way of controlling this?

- second, my confused reference to circularity in the original post was
because I couldn't see how methods with the same interface were linked.
After looking at defgeneric am I right in thinking that a generic
function is "the same kind of thing" as the list of methods that a class
has in a language like C++/Java (ie some kind of look-up table that
organises the methods by specificity etc) (this then explains why people
suggested using defgeneric in a separate package to define the
structure)?

Sorry that I keep trying to link things to unrelated languages - I
realise they are different beasts, I'm just trying to get my bearings.

Cheers,
Andrew
http://www.andrewcooke.free-online.co.uk/index.html




Sent via Deja.com http://www.deja.com/
Share what you know. Learn what you don't.
From: Tim Bradshaw
Subject: Re: Newbie Q: Methods & Packages
Date: 
Message-ID: <ey3emgd3use.fsf@lostwithiel.tfeb.org>
* Andrew Cooke wrote:

> - first, there doesn't seem to be anything in the package system that
> decides which namespace (function, variable, whatever - I remember
> something saying there were 7) within a particular package a symbol
> refers to.  Does that mean that if I have a constant and a function with
> the same name (it's OK, I've read a Lisp style guide and I have some
> common sense, but out of curiousity...) both are visible if declared
> external?  Is there no way of controlling this?

Yes it does mean that, and no there isn't.  And yes, this is sometimes
a pain -- it makes it occasionally hard to redefine bits of CL without
having side effects you might not think of -- for instance if I
designed a package where EQL was a different symbol, then (apart from
problems with things like hash tables...) things like EQL methods on
CLOS break, which is a bit subtle.  Actually EQL is a really bad
example because it's used in so many places as a default test function
so almost anything where you might expect to be able to say #'EQL
you'd have to fix. There must be other cases where there are functions
defined in the language whose names are also used, I just can't think
of one...

--tim
From: Barry Margolin
Subject: Re: Newbie Q: Methods & Packages
Date: 
Message-ID: <_5pA3.786$m84.21418@burlma1-snr2>
In article <············@nnrp1.deja.com>,
Andrew Cooke  <······@andrewcooke.free-online.co.uk> wrote:
>- first, there doesn't seem to be anything in the package system that
>decides which namespace (function, variable, whatever - I remember
>something saying there were 7) within a particular package a symbol
>refers to.  Does that mean that if I have a constant and a function with
>the same name (it's OK, I've read a Lisp style guide and I have some
>common sense, but out of curiousity...) both are visible if declared
>external?  Is there no way of controlling this?

Packages are collections of symbols, not symbol attributes.  All those
namespaces are attributes of the symbol itself.  If a symbol is visible,
all its attributes are visible.

-- 
Barry Margolin, ······@bbnplanet.com
GTE Internetworking, Powered by BBN, Burlington, 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: Erik Naggum
Subject: Re: Newbie Q: Methods & Packages
Date: 
Message-ID: <3145544479675346@naggum.no>
* Andrew Cooke
| - first, there doesn't seem to be anything in the package system that
| decides which namespace (function, variable, whatever - I remember
| something saying there were 7) within a particular package a symbol
| refers to.

  huh?  a symbol is a name of something.  a string of letters and whatever
  is the external form of that name.  when read by the Lisp reader, the
  package looks for a symbol with the name with that external form in the
  specified (or current) package, and that symbol is used.  at no point in
  this process does the "something" the symbol names enter the picture.
  however, the "something" is referenced by the user of the symbol, and if
  that is SYMBOL-VALUE, you get the variable, if it is SYMBOL-FUNCTION, it
  is the functional value, if it is FIND-CLASS, it is the class, if it is
  THROW, it it the CATCH tag with that name, but you might as well consider
  the possibility of an ASSOC list or a HASH-TABLE with a symbol as key, so
  counting namespaces is silly.

| Does that mean that if I have a constant and a function with the same
| name (it's OK, I've read a Lisp style guide and I have some common sense,
| but out of curiousity...) both are visible if declared external?

  yes.  there's nothing wrong with using the same name for several things.
  after all, that's the very idea!  it is also far better than trying to
  invent two names for the same thing.  e.g., if you have a VOTE class,
  would you want to call a function CAST-VOTE instead of just VOTE?

| Is there no way of controlling this?

  no.  the key is to understand it.  if you want some property of a symbol
  to be exportable and another not, you can either document it and expect
  people to read the documentation, or you can call it something else.

| - second, my confused reference to circularity in the original post was
| because I couldn't see how methods with the same interface were linked.
| After looking at defgeneric am I right in thinking that a generic
| function is "the same kind of thing" as the list of methods that a class
| has in a language like C++/Java (ie some kind of look-up table that
| organises the methods by specificity etc)?

  no.  skip this comparison competely until you understand it.  actively
  forget C++/Java and don't think about their way of doing things at all
  while you try to deal with CLOS methods.  it's like trying to understand
  the French "ne pas" and trying to make it match "do not" in English.  it
  works up to a point, but it doesn't actually work that way.

| (this then explains why people suggested using defgeneric in a separate
| package to define the structure)

  huh?  where did you find this suggestion?

| Sorry that I keep trying to link things to unrelated languages - I
| realise they are different beasts, I'm just trying to get my bearings.

  you will fail to relate to other languages until you have understood each
  one by itself.  you won't understand one language until you have ceased
  to want to relate to others.  different languages need to be understood
  on their own terms.  and more than anything else, make sure that you wait
  until you have _good_ reason to think two similar properties of two
  different languages are the same -- more often than not, they are very
  different, yet look deceptively the same.  take symbols in Scheme and CL,
  for instance.

#:Erik
-- 
  save the children: just say NO to sex with pro-lifers
From: Andrew Cooke
Subject: Re: Newbie Q: Methods & Packages
Date: 
Message-ID: <7qvqgk$7nt$1@nnrp1.deja.com>
In article <················@naggum.no>,
  Erik Naggum <····@naggum.no> wrote:
> * Andrew Cooke
[...]
> | (this then explains why people suggested using defgeneric in a
separate
> | package to define the structure)
>
>   huh?  where did you find this suggestion?

See other posts in this thread - quite a few have discussed it (maybe I
didn't describe it very well above).

> | Sorry that I keep trying to link things to unrelated languages - I
> | realise they are different beasts, I'm just trying to get my
bearings.
>
>   you will fail to relate to other languages until you have understood
each
>   one by itself.  you won't understand one language until you have
ceased
>   to want to relate to others.  different languages need to be
understood
>   on their own terms.  and more than anything else, make sure that you
wait
>   until you have _good_ reason to think two similar properties of two
>   different languages are the same -- more often than not, they are
very
>   different, yet look deceptively the same.  take symbols in Scheme
and CL,
>   for instance.

That's all very fine, but you are asking me to run before I can walk.
When one learns a new "real" language, one starts by making comparisons,
and only later do the more subtle differences appear.  In both that case
and computer languages it is very frustrating when an expert refuses to
make broad simplifications because they are "wrong" - it is often useful
to have something to work from, even if it is not correct.  This is how
science works for example, by progressive refinement - no-one teaches GR
before Newtonian mechanics.

I've spent some time trying to teach physics to people on the web and I
can understand why you don't want to compromise - people extrapolate
from the simplified comparison and make mistakes - but I found that if I
didn't simplify it went straight over people's heads.   In the end I
simplified (to the point where things are no longer correct), but
flagged what I was doing, so that a later reading could pick up on the
subtleties.

I guess from your name and email address and post that you speak at
least two natural languages.  Did you really learn the second by erasing
your mind and learning it like a new born child?  Or did you use useful
but erroneous comparisons with your first language, revising things as
you knew more?

People are not computers.

Andrew

PS.  Thanks for the help.  There's always more to write over
disagreements than there is over useful information read and absorbed...
:-)



Sent via Deja.com http://www.deja.com/
Share what you know. Learn what you don't.
From: Lieven Marchand
Subject: Re: Newbie Q: Methods & Packages
Date: 
Message-ID: <m3so4sgev3.fsf@localhost.localdomain>
Andrew Cooke <······@andrewcooke.free-online.co.uk> writes:

> I guess from your name and email address and post that you speak at
> least two natural languages.  Did you really learn the second by erasing
> your mind and learning it like a new born child?  Or did you use useful
> but erroneous comparisons with your first language, revising things as
> you knew more?
> 

I know four natural languages and learning it as a child - i.e. by
simply having people speak it to you in a natural context - is in my
experience indeed the best approach. You get more from simple
sentences like "My name is ..." accompanied by gestures etc. but with
the interaction in the language you want to learn than by lectures in
your language about the grammar and morphology of the language you
want to learn.

Grammar is a way of organizing the patterns you noticed in the
language spoken to you and comes later on.

-- 
Lieven Marchand <···@bewoner.dma.be>
If there are aliens, they play Go. -- Lasker
From: Barry Margolin
Subject: Re: Newbie Q: Methods & Packages
Date: 
Message-ID: <%BKA3.819$m84.21462@burlma1-snr2>
In article <············@nnrp1.deja.com>,
Andrew Cooke  <······@andrewcooke.free-online.co.uk> wrote:
>That's all very fine, but you are asking me to run before I can walk.
>When one learns a new "real" language, one starts by making comparisons,
>and only later do the more subtle differences appear.

Uh oh, you've admitted to doing something that Erik thinks is sacrilegious.
Prepared to be ridiculed; try not to take it personally.

-- 
Barry Margolin, ······@bbnplanet.com
GTE Internetworking, Powered by BBN, Burlington, 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: Rainer Joswig
Subject: Re: Newbie Q: Methods & Packages
Date: 
Message-ID: <joswig-0609991052270001@pbg3.lavielle.com>
In article <···················@burlma1-snr2>, Barry Margolin <······@bbnplanet.com> wrote:

> In article <············@nnrp1.deja.com>,
> Andrew Cooke  <······@andrewcooke.free-online.co.uk> wrote:
> >That's all very fine, but you are asking me to run before I can walk.
> >When one learns a new "real" language, one starts by making comparisons,
> >and only later do the more subtle differences appear.
> 
> Uh oh, you've admitted to doing something that Erik thinks is sacrilegious.
> Prepared to be ridiculed; try not to take it personally.

;-)
From: Erik Naggum
Subject: Re: Newbie Q: Methods & Packages
Date: 
Message-ID: <3145605465570982@naggum.no>
* Andrew Cooke <······@andrewcooke.free-online.co.uk>
| That's all very fine, but you are asking me to run before I can walk.

  huh?  what did you compare the first language you learned to?  I think
  it's you who want to run before you can walk because you want compare
  before you understand.

| When one learns a new "real" language, one starts by making comparisons,
| and only later do the more subtle differences appear.

  that's how you do it.  it has led to some problems in understanding.
  maybe the two are related?

| In both that case and computer languages it is very frustrating when an
| expert refuses to make broad simplifications because they are "wrong" -
| it is often useful to have something to work from, even if it is not
| correct.

  in a personal or controlled context, such simplifications are perfectly
  OK, since the responsibility to correct the simplification later is under
  control.  when answering something on a newsgroup, there is no telling
  what the person will go away with and believe later, without correction,
  and especially what somebody else will go away with or search for later.

| I guess from your name and email address and post that you speak at least
| two natural languages.  Did you really learn the second by erasing your
| mind and learning it like a new born child?  Or did you use useful but
| erroneous comparisons with your first language, revising things as you
| knew more?

  no, I didn't make such comparisons, but I "compared" at the meta-level,
  instead.  that is, instead of comparing the expression of a concept or
  action or whatever from language to language, I wondered how one would
  express the same concept or action or whatever in English if I had seen
  it in Norwegian and vice versa, but it has been important to me to try to
  discover the concept in each language on its own.  this has the curious
  effect that I develop vocabulary and whole concepts in each language and
  struggle to translate between the two languages, because concepts are
  often so local to the culture that a translation will always fail, which,
  by the way, is often proved beyond any doubt in the subtitling of the
  many American TV shows broadcast here.

| People are not computers.

  people who have a more methodical mind than others hear this a lot.  I
  have never quite figured out how it is a valuable statement to make in an
  argument, though.  why is being more methodical an _unhuman_ trait?

#:Erik
-- 
  save the children: just say NO to sex with pro-lifers
From: Andrew Cooke
Subject: Re: Newbie Q: Methods & Packages
Date: 
Message-ID: <7r0elm$kql$1@nnrp1.deja.com>
In article <················@naggum.no>,
  Erik Naggum <····@naggum.no> wrote:
> * Andrew Cooke <······@andrewcooke.free-online.co.uk>
> | People are not computers.
>
>   people who have a more methodical mind than others hear this a lot.
I
>   have never quite figured out how it is a valuable statement to make
in an
>   argument, though.  why is being more methodical an _unhuman_ trait?

Maybe you have to realise that you are more methodical than the people
you are talking to - after all, when explaining you should be aiming at
the learner, not yourself.

Applying the same advice to myself: since I last posted I've been
wondering about this, and I think we may be at opposite ends of some
kind of spectrum in how we use language.  I understand things at a very
"unconscious" level (this is difficult to explain!) - I often find it
very hard to express exactly what I mean and am often left hunting for
the right word or annoying people by being too lax in my terminology
(this hasn't harmed me academically, although it can give a bad initial
impression, I think).  Sometimes I meet people (I work with one - hello
Andreas! :-) who can be  (appear, to me) literal and pedantic to the
point of (to me, again) obsessiveness - they can drive me up the wall...

Anyway, no more from me on this non-Lisp topic....

Cheers,
Andrew



Sent via Deja.com http://www.deja.com/
Share what you know. Learn what you don't.
From: Tim Bradshaw
Subject: Re: Newbie Q: Methods & Packages
Date: 
Message-ID: <ey3906k4795.fsf@lostwithiel.tfeb.org>
* Andrew Cooke wrote:
> That's all very fine, but you are asking me to run before I can walk.
> When one learns a new "real" language, one starts by making comparisons,
> and only later do the more subtle differences appear.  In both that case
> and computer languages it is very frustrating when an expert refuses to
> make broad simplifications because they are "wrong" - it is often useful
> to have something to work from, even if it is not correct.  This is how
> science works for example, by progressive refinement - no-one teaches GR
> before Newtonian mechanics.

But I think this is kind of wrong in an important way.  I think you
are a physicist so you'll have learnt quantum mechanics at some point.

When I learnt QM, I went through some weeks of pain because I was
trying to relate it to the classical mechanics I already knew.  Then
one day I had a classic `ah...' experience, in my case in a tutorial
when the tutor asked the classic `what happens if you reduce the
number of particles in the 2 slit experiment so that there is only one
in the experiment at once?' question.  What I realised then was that
QM was just totally different and weird and *nothing like* anything I
knew from classical mechanics[1].

Interestingly, the lecturers & tutors were fairly consciously trying
to get you to this point when you suddenly understood that it was all
weird and different, which they did by asking these kind of leading
questions like the 2 slit one above.  So they were really aiming at
this sudden realisation thing, which I think was delayed by trying to
understand it in terms of things you knew.  I think understanding of
QM was delayed originally by this problem as well.


Obviously, Lisp is not as weird compared to C/C++/whatever as QM is
compared to classical mechanics -- it's just a programming language!
But there is a certain amount of the same problem there, and there are
certain points where you need to really have that `oh, it's not like
this' experience.  I think macros, and some aspects of CLOS are a
bit like this.  Interestingly, as with QM, once you *do* understand,
say, CLOS, you can look back on something like the C++ object system
and see that it's really just a special limiting case of this more
general thing (CLOS) that you now understand.

--tim


[1] Of course, the mathematics of it is quite closely related in a
kind of weird way (I certainly got a lot of benefit out of classical
Hamiltonian/Lagrangian mechanics when doing the maths of QM.  But I
think the physical nature of the thing is still fundamentally other
than classical mechanics.
From: William Deakin
Subject: Re: Newbie Q: Methods & Packages
Date: 
Message-ID: <37D3B1DC.435A9A40@pindar.com>
Tim Bradshaw wrote:

> ...Of course, the mathematics of it is quite closely related in a kind of
> weird way (I certainly got a lot of benefit out of classical
> Hamiltonian/Lagrangian mechanics when doing the maths of QM.

There are also strong similarities to the mathematics of physical optics.

> But  I think the physical nature of the thing is still fundamentally other
> than classical mechanics.

But maybe similar to optics?

Best Regards,

:-) will
From: Martin Rodgers
Subject: Re: Newbie Q: Methods & Packages
Date: 
Message-ID: <MPG.123de12edc1d0ef998a001@news.demon.co.uk>
In article <············@nnrp1.deja.com>, ······@andrewcooke.free-
online.co.uk says...

> I've spent some time trying to teach physics to people on the web and I
> can understand why you don't want to compromise - people extrapolate
> from the simplified comparison and make mistakes - but I found that if I
> didn't simplify it went straight over people's heads.   In the end I
> simplified (to the point where things are no longer correct), but
> flagged what I was doing, so that a later reading could pick up on the
> subtleties.
 
In the Pratchett/Sterwart/Cohen book, The Science of Discworld, this 
is called lies-to-children. "A lie-to-children is a statement that is 
false, but which nevertheless leads the child's mind towards a more 
accurate explanation, one that the child will only be able to 
appreciate if it has been primed with the lie." Variations exist, like 
lies-to-students, lies-to-bosses (Dilbert), lies-to-patients, etc. 
More details on page 38 of the book mentioned above.

The same technique is used in SICP, in which four explanations of 
Scheme's semantics are given, three of which are lies-to-readers.

Lies-to-newbies?

> People are not computers.

Even computers can start with a lie. We call them bootstraps. ;)
-- 
Remove insect from address | You can never browse enough
will write code that writes code that writes code for food
From: Lieven Marchand
Subject: Re: Newbie Q: Methods & Packages
Date: 
Message-ID: <m3aer14ez7.fsf@localhost.localdomain>
Andrew Cooke <······@andrewcooke.free-online.co.uk> writes:

> After looking at defgeneric am I right in thinking that a generic
> function is "the same kind of thing" as the list of methods that a class
> has in a language like C++/Java (ie some kind of look-up table that
> organises the methods by specificity etc) (this then explains why people
> suggested using defgeneric in a separate package to define the
> structure)?
> 

Not really. Generic functions are entities separate from classes. A
generic function does not belong to or is associated with any single
class. If you want to use your terminology, one could say that a
generic function is a list of signatures for which it has an
implementation.

A collection of defgenerics in a package can be used to define an
abstract protocol (an interface in Java if you want). Suppose you want
to write a database backend independent sql interface for lisp. You
could define a package SQL-GENERIC that has a number of classes and
defgenerics and you would document the requirements on these
functions. Then people could write a package SQL-ORACLE using
SQL-GENERIC, where they could derive from your classes and implement
the defgenerics for their classes.

-- 
Lieven Marchand <···@bewoner.dma.be>
If there are aliens, they play Go. -- Lasker
From: Tim Bradshaw
Subject: Re: Newbie Q: Methods & Packages
Date: 
Message-ID: <ey3btbh3unw.fsf@lostwithiel.tfeb.org>
* Lieven Marchand wrote:
> A collection of defgenerics in a package can be used to define an
> abstract protocol (an interface in Java if you want). Suppose you want
> to write a database backend independent sql interface for lisp. You
> could define a package SQL-GENERIC that has a number of classes and
> defgenerics and you would document the requirements on these
> functions. Then people could write a package SQL-ORACLE using
> SQL-GENERIC, where they could derive from your classes and implement
> the defgenerics for their classes.

This is a much better explanation of what I was trying to describe as
`defining a bunch of generic functions in a package' earlier on.
Thank you.

--tim
From: Robert Monfera
Subject: Re: Newbie Q: Methods & Packages
Date: 
Message-ID: <37D20966.154DA815@fisec.com>
"Thomas A. Russ" wrote:
[Detailed explanation on package constraints]

As packages group symbols, they can be best used to establish domain
languages. Because the term 'domain language' sounds a bit vague, you
may substitute it with 'language being used when discussing problems of
a specific paradigm or profession', like that of accounting, data model
design, planning&scheduling or consumer lending.

The methods trivially belong to the same package as the generic
function, because invoking a generic function is saying 'the program
does X', and the methods are the _implementation_ (i.e., explanation of
how it is being done), . You would associate the meaning of a symbol at
the generic function level. Stylistically it is preferable to use
DEFGENERIC anyway, as a documentation string and the package it belongs
to makes X more explicitly defined. Having considered these, the thought
of having 'cross-package' GF's will vanish.

This is not to say that paradigms never share the same word with
analogous meanings: for example one could conclude that the verb
'commit' should have a method in the "LENDING" package, and another in
the "ODBC" package. In this case I would rather keep them (i.e., the
GF's) separate, because it is somewhat incidental that the symbol and
the meaning corresponds to one another (both domain languages borrow
from English). This still allows you to have a thin method definition
for a committing a loan in case a loan committment in your application
does not mean more than committing insertions and updates of database
records. 

(in-package "LENDING")

(defgeneric commit (loan)
    (:documentation
     "Approves a loan. This is a prerequisite step
     of disbursing the loan. It is required that
     the loan application is complete. Returns 
     approval number if successful, otherwise nil."))

(defmethod commit ((loan business-loan))
   (odbc:commit loan))

You also gain the freedom to extend your definitions if necessary:

(defmethod commit ((loan large-corporate-loan))
   (when (mqseries:send-message :confirm loan sys:*LS2-system*)
      (intranet:send-email loan :approved *executive-board*)))

You can also rename your GF to 'approve' after learning that bankers are
more likely to use that term.

> Packages in Lisp are meant to separate collections of lisp code that are
> not expected to interact heavily with each other. 

Yes, it is true that packages should come with low coupling and high
cohesion. The above code example heavily uses things from other packages
though, as it is commuting among various paradigms. I can imagine sound
real life code where most definitions (besides utilities) contain
foreign symbols - it's eventually the developer building bridges between
what he wants and what he has. This also demonstrates why developers
must be very knowledgeable about the problem domain, besides techical
knowledge (IT), CS and other areas.

Take care
Robert
From: Pierre R. Mai
Subject: Re: Newbie Q: Methods & Packages
Date: 
Message-ID: <87k8q8gm6d.fsf@orion.dent.isdn.cs.tu-berlin.de>
Andrew Cooke <······@andrewcooke.free-online.co.uk> writes:

> I suspect I already know the answer to this, but coming from less
> dynamic languages am unwilling to trust it without confirmation :)
> 
> I have an application which I would like to spread over several packages
> (not being used to multimethods I feel happier grouping methods with
> classes inside packages, although one package may hold several related
> classes - is this normal practice?).  The classes and main methods will
> be exported (declared external).

As far as normal practice is concerned, it seems to me that you are
using packages at a too fine a level.  Normal practice would make
packages be the size of a library or subsystem, i.e. in a given
medium-sized application, one would have a couple of packages (less
than 10?) at most, unless the application falls into many disparate
pieces.

What you are trying to do seems more like orthodox encapsulation of
classes into packages.  General advice seems to be that this is clumsy 
at best, leading to hard to track dependencies and naming hassles,
like the one below...

> My question is - will method chaining work correctly across packages?

Packages have nothing to do with methods and generic functions per
se.  The package system is about naming (i.e. it is _not_ a module
system or similar things) and visibility of names, and nothing else.
The package system deals in symbols, which are used in turn by other
parts of the language as naming devices (among other things).

> For example, I might have (all external):
> 
> package animals:
> class animal
> class food
> method eat(animal, food)
> method kill(food)
> 
> package Cows:
> class Cow(animal)
> class Grass(food)
> method eat(cow, grass)
> method kill(grass)

In cases like this, always think of symbols and not of methods:  If
you don't take any special measures, then cows::eat and animals::eat
will name different symbols, and therefore cows::eat and animals::eat
will name different generic functions, which know nothing about one
another.

If you want to avoid this, you will have to make sure that cows::eat
and animals::eat will name the same symbol, either by importing one
from the other package, or using the other package or a third package
outright.

One example to make this work would be:

(cl:defpackage "ANIMALS"
  (:USE "CL")
  (:EXPORT "ANIMAL" "FOOD" "EAT" "KILL"))

(cl:in-package "ANIMALS")

(defclass animal ()
  ((name :initarg :name :accessor animal-name)))
(defclass food ()
  ((name :initarg :name :accessor food-name)))

(defmethod print-object ((obj animal) stream)
  (print-unreadable-object (obj stream :type t :identity t)
    (format stream "~A" (animal-name obj))))

(defmethod print-object ((obj food) stream)
  (print-unreadable-object (obj stream :type t :identity t)
    (format stream "~A" (food-name obj))))

(defgeneric eat (who what) 
  (:documentation "Let's WHO eat WHAT, killing it in the process."))
(defgeneric kill (what)
  (:documentation "Kills WHAT."))

(defmethod eat ((who animal) (what food))
  (format t "~A eats ~A~%" who what)
  (kill what))
(defmethod kill ((what food))
  (format t "~A is killed!~%" what))

(cl:defpackage "COWS"
  (:USE "CL" "ANIMALS")
  (:EXPORT "COW" "GRASS" "EAT" "KILL"))

(cl:in-package "COWS")

(defclass cow (animal)
  ()
  (:default-initargs :name "Muh"))
(defclass grass (food)
  ()
  (:default-initargs :name "Hasch"))

(defmethod eat ((who cow) (what grass))
  (call-next-method)
  (format t "~A is redigesting ~A...~%" who what))
(defmethod kill ((what grass))
  (call-next-method)
  (format t "~A is not dead!~%" what))

;;; Demo usage:

* (cl:defpackage "TRIALPKG" (:USE "CL" "ANIMALS" "COWS"))
#<The TRIALPKG package, 0/9 internal, 0/2 external>
* (cl:in-package "TRIALPKG")
#<The TRIALPKG package, 0/9 internal, 0/2 external>
* (make-instance 'cow)
#<COW Muh {481899AD}>
* (make-instance 'grass)
#<GRASS Hasch {4818A10D}>
* (eat ** *)
#<COW Muh {481899AD}> eats #<GRASS Hasch {4818A10D}>
#<GRASS Hasch {4818A10D}> is killed!
#<GRASS Hasch {4818A10D}> is not dead!
#<COW Muh {481899AD}> is redigesting #<GRASS Hasch {4818A10D}>...
NIL

> Now if eat(a-cow, some-grass) is called, and subsequently calls the more
> general eat(animal, food), which in turn calls kill(food), will
> kill(grass) be called first (being the most specific method)?  Will this
> happen even if the call is from an intermediate method that is not
> exported?  What do I need to add to the files so that the two packages
> know of each other?  Is (use-package "animals") in cows and (use-package
> "cows") in animals sufficient?  Will this compile ok (containing
> circular references)?

If we stay in your conceptual frame of reference (which seems to be
"traditional" OOP), then why would ANIMALS need to use (or be allowed
to use) COWS?  COWS needs (might prefer) to use ANIMALS, since it uses
ANIMALS infrastructure to define COWS and GRASS, but ANIMALS has no
dependencies on COWS, does it?

All in all this OO-centric approach to package design often (though
not in this case) leads to circular package dependencies, which should
be avoided.  I'd suggest that you take a look at the freely available
source code out there to see how packages are used in practice.[1]
Also browse Deja News about comp.lang.lisp and postings on the use of
packages, where you will find illuminating comments on this topic.

Regs, Pierre.

Footnotes: 
[1]  Should you happen to look at the source code for MaiSQL (see
http://www.pmsf.de/pmai/),  please note: The use of packages in MaiSQL
SEEMS to mirror your approach, but in fact does not: The reason why
each implementation database class is in it's own package has more to
do with subsystem partitioning and the hiding of symbols introduced by
the foreign function interfaces than with OOP encapsulation.  Also
note that the implementation packages are internal and thus irrelevant
to the user of MaiSQL...

-- 
Pierre Mai <····@acm.org>         PGP and GPG keys at your nearest Keyserver
  "One smaller motivation which, in part, stems from altruism is Microsoft-
   bashing." [Microsoft memo, see http://www.opensource.org/halloween1.html]
From: Andrew Cooke
Subject: Re: Newbie Q: Methods & Packages
Date: 
Message-ID: <7qosil$kj9$1@nnrp1.deja.com>
Thanks for all the detailed help.  I understand the point about symbols
now.  I will:

- use larger packages
- check other source

Cheers,
Andrew
http://www.andrewcooke.free-online.co.uk/index.html


Sent via Deja.com http://www.deja.com/
Share what you know. Learn what you don't.
From: Espen Vestre
Subject: Re: Newbie Q: Methods & Packages
Date: 
Message-ID: <w6r9kgqg2g.fsf@wallace.nextel.no>
Andrew Cooke <······@andrewcooke.free-online.co.uk> writes:

> Now if eat(a-cow, some-grass) is called, and subsequently calls the more
> general eat(animal, food), which in turn calls kill(food), will
> kill(grass) be called first (being the most specific method)?  Will this
> happen even if the call is from an intermediate method that is not
> exported?  What do I need to add to the files so that the two packages
> know of each other?  Is (use-package "animals") in cows and (use-package
> "cows") in animals sufficient?  Will this compile ok (containing
> circular references)?

very briefly: Even if the two packages USE each other, there will be
two distinct generic functions ANIMALS::EAT and COWS::EAT as long 
as you don't export the EAT symbol.  In order to make it the same
symbol, you need to export it (and then, of course, you'll be asked
whether to resolve the conflict if it already exists in both
packages).

(packages is not easy stuff, but try to read the literature.  And
 don't try to confuse it with the OO part.  Packages are basically
 the business of the *reader* (are you used to perl?))
-- 
  (espen)