From: Erann Gat
Subject: CLOS and databases
Date: 
Message-ID: <gNOSPAMat-1903041117510001@k-137-79-50-101.jpl.nasa.gov>
I'm working on a simple object database built on top of a relational
database.  My current design is to have a "storable" mixin class which
defines two methods, STORE and RETRIEVE, which do the obvious things.

A problem with this simple design is that it places a burden on the user
to keep track of the relative states of the objects in memory and in the
DB, and to decide when to STORE and RETRIEVE them.  It would be nice to
make this transparent so that any reference to a slot of a STORABLE object
would transparently synchronize to the DB.  I had envisioned implementing
this using a :before method on the slot-value  and (setf slot-value)
methods which would check to make sure everything was in sync.

Is there a better way to do it?  Is this a job for the MOP?

My goal here is not only to make something functional, but also to
highlight the power of CLOS with something that will really knock the
socks off the Java people, so I really want to do this the Right Way.

E.

From: Erann Gat
Subject: Re: CLOS and databases
Date: 
Message-ID: <gNOSPAMat-1903041123550001@k-137-79-50-101.jpl.nasa.gov>
In article <··························@k-137-79-50-101.jpl.nasa.gov>,
·········@jpl.nasa.gov (Erann Gat) wrote:

>I had envisioned implementing
> this using a :before method on the slot-value  and (setf slot-value)
> methods which would check to make sure everything was in sync.

That should read MY-SLOT-VALUE and (SETF MY-SLOT-VALUE).  SLOT-VALUE is
not a generic function.

E.
From: Joe Marshall
Subject: Re: CLOS and databases
Date: 
Message-ID: <ptb8egyy.fsf@ccs.neu.edu>
·········@jpl.nasa.gov (Erann Gat) writes:

> In article <··························@k-137-79-50-101.jpl.nasa.gov>,
> ·········@jpl.nasa.gov (Erann Gat) wrote:
>
>>I had envisioned implementing
>> this using a :before method on the slot-value  and (setf slot-value)
>> methods which would check to make sure everything was in sync.
>
> That should read MY-SLOT-VALUE and (SETF MY-SLOT-VALUE).  SLOT-VALUE is
> not a generic function.

That would end up requiring a transaction on every store!
From: Erann Gat
Subject: Re: CLOS and databases
Date: 
Message-ID: <gNOSPAMat-1903041218500001@k-137-79-50-101.jpl.nasa.gov>
In article <············@ccs.neu.edu>, Joe Marshall <···@ccs.neu.edu> wrote:

> ·········@jpl.nasa.gov (Erann Gat) writes:
> 
> > In article <··························@k-137-79-50-101.jpl.nasa.gov>,
> > ·········@jpl.nasa.gov (Erann Gat) wrote:
> >
> >>I had envisioned implementing
> >> this using a :before method on the slot-value  and (setf slot-value)
> >> methods which would check to make sure everything was in sync.
> >
> > That should read MY-SLOT-VALUE and (SETF MY-SLOT-VALUE).  SLOT-VALUE is
> > not a generic function.
> 
> That would end up requiring a transaction on every store!

TANSTAAFL.  But 1) it requires an update, not a transaction and 2) I have
a scheme whereby multiple updates get queued up and only written to the DB
when they're actually needed.

E.
From: Will Hartung
Subject: Re: CLOS and databases
Date: 
Message-ID: <c3fq6t$26orfl$1@ID-197644.news.uni-berlin.de>
"Erann Gat" <·········@jpl.nasa.gov> wrote in message
·······························@k-137-79-50-101.jpl.nasa.gov...
> In article <············@ccs.neu.edu>, Joe Marshall <···@ccs.neu.edu>
wrote:
> > That would end up requiring a transaction on every store!
>
> TANSTAAFL.  But 1) it requires an update, not a transaction and 2) I have
> a scheme whereby multiple updates get queued up and only written to the DB
> when they're actually needed.

If you write to the DB (that is any standard generic modern SQL DB, and
specifically excluding mySQL), you get a transaction for every write no
matter what. The distinction being whether the transaction persists or
commits at the end of the write.

The other way, depending on what you want to do, is to simply flag the
entire object (and, perhaps the slot) for update and then on your Big Commit
you can either flush the entire thing, or if your noting slots, do a smart
update.

Obviously, one is simpler and more basic to do than the other.

It also depends on whether you want to be able to rollback object changes.

(setf object (make-instance 'persistent-user-class))

(setf (userid-key-slot object) "ID1234")

(retrieve object)

(print (first-name object))
"BOB"

(begin-transaction)

(setf (first-name object) "SAM")

(rollback-transaction)

(print (first-name object))

???

These are some of the fun problems persistence framework guys get to fight
with :-), and how "transparent" persistence really is/isn't.

Regards,

Will Hartung
(·····@msoft.com)
From: Erann Gat
Subject: Re: CLOS and databases
Date: 
Message-ID: <gNOSPAMat-1903041524590001@k-137-79-50-101.jpl.nasa.gov>
In article <···············@ID-197644.news.uni-berlin.de>, "Will Hartung"
<·····@msoft.com> wrote:

> "Erann Gat" <·········@jpl.nasa.gov> wrote in message
> ·······························@k-137-79-50-101.jpl.nasa.gov...
> > In article <············@ccs.neu.edu>, Joe Marshall <···@ccs.neu.edu>
> wrote:
> > > That would end up requiring a transaction on every store!
> >
> > TANSTAAFL.  But 1) it requires an update, not a transaction and 2) I have
> > a scheme whereby multiple updates get queued up and only written to the DB
> > when they're actually needed.
> 
> If you write to the DB (that is any standard generic modern SQL DB, and
> specifically excluding mySQL)

I am in fact using mySQL precisely for that reason.  I want a simple,
efficient, indexed persistent store, not ACID.

E.
From: John Thingstad
Subject: Re: CLOS and databases
Date: 
Message-ID: <opr44p2skfxfnb1n@news.chello.no>
Newer versions of mysql have two modes.
One supports rollback so excluding it would be wrong if I understand you 
right.

On Fri, 19 Mar 2004 14:10:31 -0800, Will Hartung <·····@msoft.com> wrote:

> If you write to the DB (that is any standard generic modern SQL DB, and
> specifically excluding mySQL), you get a transaction for every write no
> matter what. The distinction being whether the transaction persists or
> commits at the end of the write.



-- 
Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
From: Joe Marshall
Subject: Re: CLOS and databases
Date: 
Message-ID: <65d0gzgt.fsf@comcast.net>
·········@jpl.nasa.gov (Erann Gat) writes:

> In article <············@ccs.neu.edu>, Joe Marshall <···@ccs.neu.edu> wrote:
>
>> ·········@jpl.nasa.gov (Erann Gat) writes:
>> 
>> > In article <··························@k-137-79-50-101.jpl.nasa.gov>,
>> > ·········@jpl.nasa.gov (Erann Gat) wrote:
>> >
>> >>I had envisioned implementing
>> >> this using a :before method on the slot-value  and (setf slot-value)
>> >> methods which would check to make sure everything was in sync.
>> >
>> > That should read MY-SLOT-VALUE and (SETF MY-SLOT-VALUE).  SLOT-VALUE is
>> > not a generic function.
>> 
>> That would end up requiring a transaction on every store!
>
> TANSTAAFL.  But 1) it requires an update, not a transaction and 2) I have
> a scheme whereby multiple updates get queued up and only written to the DB
> when they're actually needed.

But you said before:
  ``It would be nice to make this transparent so that any reference to
    a slot of a STORABLE object would transparently synchronize to the DB.''

Either the lisp system is synchronized or it isn't.

-- 
~jrm
From: Erann Gat
Subject: Re: CLOS and databases
Date: 
Message-ID: <gNOSPAMat-1903041705290001@k-137-79-50-101.jpl.nasa.gov>
In article <············@comcast.net>, Joe Marshall
<·············@comcast.net> wrote:

> ·········@jpl.nasa.gov (Erann Gat) writes:
> 
> > In article <············@ccs.neu.edu>, Joe Marshall <···@ccs.neu.edu> wrote:
> >
> >> ·········@jpl.nasa.gov (Erann Gat) writes:
> >> 
> >> > In article <··························@k-137-79-50-101.jpl.nasa.gov>,
> >> > ·········@jpl.nasa.gov (Erann Gat) wrote:
> >> >
> >> >>I had envisioned implementing
> >> >> this using a :before method on the slot-value  and (setf slot-value)
> >> >> methods which would check to make sure everything was in sync.
> >> >
> >> > That should read MY-SLOT-VALUE and (SETF MY-SLOT-VALUE).  SLOT-VALUE is
> >> > not a generic function.
> >> 
> >> That would end up requiring a transaction on every store!
> >
> > TANSTAAFL.  But 1) it requires an update, not a transaction and 2) I have
> > a scheme whereby multiple updates get queued up and only written to the DB
> > when they're actually needed.
> 
> But you said before:
>   ``It would be nice to make this transparent so that any reference to
>     a slot of a STORABLE object would transparently synchronize to the DB.''
> 
> Either the lisp system is synchronized or it isn't.

Or both.  Sometimes core and disk are synchronized and sometimes they are
not, much like virtual memory or file buffers.  What I mean by
transparency is that when you decide you want to render the current state
of things to disk you can simply call "sync" and everything gets taken
care of for you without you having to know or care about what is and is
not being written.  If you make changes and forget to call sync, or Lisp
crashes, then you lose, just as you lose if your unix crashes with
unflushed file buffers.  But Lisp never crashes, so that's not really a
problem :-)

E.
From: Rahul Jain
Subject: Re: CLOS and databases
Date: 
Message-ID: <87brmsnt45.fsf@nyct.net>
·········@jpl.nasa.gov (Erann Gat) writes:

> I'm working on a simple object database built on top of a relational
> database.  My current design is to have a "storable" mixin class which
> defines two methods, STORE and RETRIEVE, which do the obvious things.

Would (un)commonSQL do the job?

-- 
Rahul Jain
·····@nyct.net
Professional Software Developer, Amateur Quantum Mechanicist
From: Erann Gat
Subject: Re: CLOS and databases
Date: 
Message-ID: <gNOSPAMat-1903041854300001@192.168.1.51>
In article <··············@nyct.net>, Rahul Jain <·····@nyct.net> wrote:

> ·········@jpl.nasa.gov (Erann Gat) writes:
> 
> > I'm working on a simple object database built on top of a relational
> > database.  My current design is to have a "storable" mixin class which
> > defines two methods, STORE and RETRIEVE, which do the obvious things.
> 
> Would (un)commonSQL do the job?

Too complicated for my tastes.  Also, it didn't work in MCL the last time
I checked.

E.
From: Alain Picard
Subject: Re: CLOS and databases
Date: 
Message-ID: <87wu5g140h.fsf@memetrics.com>
·········@jpl.nasa.gov (Erann Gat) writes:

> In article <··············@nyct.net>, Rahul Jain <·····@nyct.net> wrote:
>
>> ·········@jpl.nasa.gov (Erann Gat) writes:
>> 
>> > I'm working on a simple object database built on top of a relational
>> > database.  My current design is to have a "storable" mixin class which
>> > defines two methods, STORE and RETRIEVE, which do the obvious things.
>> 
>> Would (un)commonSQL do the job?
>
> Too complicated for my tastes.  Also, it didn't work in MCL the last time
> I checked.
>

Well, what your asking for _IS_ complicated.  We wrote a set of
wrappers around Xanaly's CommonSQL to make it look even 
more "transparent", and I tell you it was seriously hairy and
still somewhat brittle.  (Of course, we cared about ACID etc.).

What about PLOB! ?

Also, look into the berkeley-db interface which might be nicer
for simple stuff than the whole-hog SQL.
From: Erann Gat
Subject: Re: CLOS and databases
Date: 
Message-ID: <gNOSPAMat-1903042332270001@192.168.1.51>
In article <··············@memetrics.com>, Alain Picard
<············@memetrics.com> wrote:

> ·········@jpl.nasa.gov (Erann Gat) writes:
> 
> > In article <··············@nyct.net>, Rahul Jain <·····@nyct.net> wrote:
> >
> >> ·········@jpl.nasa.gov (Erann Gat) writes:
> >> 
> >> > I'm working on a simple object database built on top of a relational
> >> > database.  My current design is to have a "storable" mixin class which
> >> > defines two methods, STORE and RETRIEVE, which do the obvious things.
> >> 
> >> Would (un)commonSQL do the job?
> >
> > Too complicated for my tastes.  Also, it didn't work in MCL the last time
> > I checked.
> >
> 
> Well, what your asking for _IS_ complicated.

No, I don't think so.  (And I back up that assertion with the fact that
I've got a lot of it working already.)  But I'm curious, what is it that
you think I'm asking for that's complicated?

> What about PLOB! ?

Doesn't run on MCL, and probably can't be ported because MCL doesn't
support the full MOP and plob seems to rely on that (at least judging from
a cursory glance at the docs).

> Also, look into the berkeley-db interface which might be nicer
> for simple stuff than the whole-hog SQL.

A good suggestion, but I've already got a mySQL interface up and running,
so I'm going to stick with that.

E.
From: james anderson
Subject: Re: CLOS and databases
Date: 
Message-ID: <405C5802.693565F@setf.de>
Erann Gat wrote:
> 
> ...
> 
> > What about PLOB! ?
> 
> Doesn't run on MCL, and probably can't be ported because MCL doesn't
> support the full MOP and plob seems to rely on that (at least judging from
> a cursory glance at the docs).

when i last asked, there was also the issue with the license for the
underlying database.

...
From: Alain Picard
Subject: Re: CLOS and databases
Date: 
Message-ID: <87smg40won.fsf@memetrics.com>
·········@jpl.nasa.gov (Erann Gat) writes:

> In article <··············@memetrics.com>, Alain Picard
> <············@memetrics.com> wrote:
>
>> ·········@jpl.nasa.gov (Erann Gat) writes:
>> 
>> > In article <··············@nyct.net>, Rahul Jain <·····@nyct.net> wrote:
>> >
>> >> ·········@jpl.nasa.gov (Erann Gat) writes:
>> >> 
>> >> > I'm working on a simple object database built on top of a relational
>> >> > database.  My current design is to have a "storable" mixin class which
>> >> > defines two methods, STORE and RETRIEVE, which do the obvious things.
>> >> 
>> >> Would (un)commonSQL do the job?
>> >
>> > Too complicated for my tastes.  Also, it didn't work in MCL the last time
>> > I checked.
>> >
>> 
>> Well, what your asking for _IS_ complicated.
>
> No, I don't think so.  (And I back up that assertion with the fact that
> I've got a lot of it working already.)  But I'm curious, what is it that
> you think I'm asking for that's complicated?

Hum... maybe I shouldn't have said that.  Maybe I should have
said: what you _want_, but may not know you want, is complicated.

To be honest, maybe that should say: what I wanted (and implemented)
turned out to be far more complicated that I originally thought.
From: Erann Gat
Subject: Re: CLOS and databases
Date: 
Message-ID: <gNOSPAMat-2003040908510001@192.168.1.51>
In article <··············@memetrics.com>, Alain Picard
<············@memetrics.com> wrote:

> Hum... maybe I shouldn't have said that.  Maybe I should have
> said: what you _want_, but may not know you want, is complicated.

Ah.  Well, obviously I wouldn't know about that :-)

E.
From: David Magda
Subject: Re: CLOS and databases
Date: 
Message-ID: <86k71fxv7a.fsf@number6.magda.ca>
Rahul Jain <·····@nyct.net> writes:

> ·········@jpl.nasa.gov (Erann Gat) writes:
> 
> > I'm working on a simple object database built on top of a
> > relational database.  My current design is to have a "storable"
> > mixin class which defines two methods, STORE and RETRIEVE, which
> > do the obvious things.
> 
> Would (un)commonSQL do the job?

Has the OP tried looking at "object prevalence"?

http://www.advogato.org/article/398.html
http://www-106.ibm.com/developerworks/library/wa-objprev/

Some Lisp code at:

http://www.prevayler.org/wiki.jsp?topic=PrevaylerPortsToOtherLanguages

I first read about it in "Rebel With A Cause":

http://homepage.mac.com/svc/RebelWithACause/index.html

-- 
David Magda <dmagda at ee.ryerson.ca>, http://www.magda.ca/
Because the innovator has for enemies all those who have done well under
the old conditions, and lukewarm defenders in those who may do well 
under the new. -- Niccolo Machiavelli, _The Prince_, Chapter VI
From: Erann Gat
Subject: Re: CLOS and databases
Date: 
Message-ID: <gNOSPAMat-2003041316450001@192.168.1.51>
In article <··············@number6.magda.ca>, David Magda
<··················@ee.ryerson.ca> wrote:

> Rahul Jain <·····@nyct.net> writes:
> 
> > ·········@jpl.nasa.gov (Erann Gat) writes:
> > 
> > > I'm working on a simple object database built on top of a
> > > relational database.  My current design is to have a "storable"
> > > mixin class which defines two methods, STORE and RETRIEVE, which
> > > do the obvious things.
> > 
> > Would (un)commonSQL do the job?
> 
> Has the OP tried looking at "object prevalence"?

I have now.

Object prevalence seems to me no different than dumping a Lisp image,
which most Lisps provide by default.  Seems like yet another example of
Java folks reinventing a thirty year old wheel (notwithstanding that it
was then adapted by a Common Lisper).  I am at a loss to understand what
functionality Common Lisp prevalence is supposed to provide that an image
dump does not.

E.
From: Alan Shutko
Subject: Re: CLOS and databases
Date: 
Message-ID: <87hdwjrp1w.fsf@wesley.springies.com>
·········@jpl.nasa.gov (Erann Gat) writes:

> I am at a loss to understand what functionality Common Lisp
> prevalence is supposed to provide that an image dump does not.

Upgrading to a new implementation?  

-- 
Alan Shutko <···@acm.org> - I am the rocks.
Calvin: Calvin? Who's Calvin? I'm *Stupendous Man*!
From: Edi Weitz
Subject: Re: CLOS and databases
Date: 
Message-ID: <m34qsjxgot.fsf@bird.agharta.de>
On Sat, 20 Mar 2004 13:16:45 -0800, ·········@jpl.nasa.gov (Erann Gat) wrote:

> In article <··············@number6.magda.ca>, David Magda
> <··················@ee.ryerson.ca> wrote:
>
>> Has the OP tried looking at "object prevalence"?
>
> I have now.
>
> Object prevalence seems to me no different than dumping a Lisp
> image, which most Lisps provide by default.  Seems like yet another
> example of Java folks reinventing a thirty year old wheel
> (notwithstanding that it was then adapted by a Common Lisper).  I am
> at a loss to understand what functionality Common Lisp prevalence is
> supposed to provide that an image dump does not.

1. In several CL implementations saving an image will force you to
   quit your application.

2. Saving an image will most likely write megabytes of data to the
   disk.

So you're saying that each time the state of one of your persistent
objects changes you want to do this? Or rather you are implying that
the folks working on (Common Lisp) object prevalence are dumb enough
to do this? Looks to me like you haven't really understood what you
read and instead preferred to make bold claims...

Note that I'm not saying that object prevalence is or is not a good
solution for object persistence. I just fail to see how this is "no
different than dumping a Lisp image."

Edi.
From: David Magda
Subject: Re: CLOS and databases
Date: 
Message-ID: <863c82t0dh.fsf@number6.magda.ca>
·········@jpl.nasa.gov (Erann Gat) writes:
[...]
> I am at a loss to understand what functionality Common Lisp
> prevalence is supposed to provide that an image dump does not.

Depending on your data set you may not want to dump everything.

Do a whole dump at low traffic areas, but do quick
serialization/transaction logs as objects are changed. This way you
have your data as of 4am, but have all the changes that occured
throughout the day should the server go own at 11pm.

In your serialization code you code also have synchoronization code
between servers so that you can do load balancing and have hot-spares
of services.

If some corruption of the data should also occur for whatever reason
you can go a step-through of the transaction log up to the point data
was still clean.

Just some thoughts; they may or may not be useful in your particular
situation.

-- 
David Magda <dmagda at ee.ryerson.ca>, http://www.magda.ca/
Because the innovator has for enemies all those who have done well under
the old conditions, and lukewarm defenders in those who may do well 
under the new. -- Niccolo Machiavelli, _The Prince_, Chapter VI
From: Erann Gat
Subject: Re: CLOS and databases
Date: 
Message-ID: <gNOSPAMat-2103041257320001@192.168.1.51>
In article <··············@number6.magda.ca>, David Magda
<··················@ee.ryerson.ca> wrote:

> ·········@jpl.nasa.gov (Erann Gat) writes:
> [...]
> > I am at a loss to understand what functionality Common Lisp
> > prevalence is supposed to provide that an image dump does not.
> 
> Depending on your data set you may not want to dump everything.
> 
> Do a whole dump at low traffic areas, but do quick
> serialization/transaction logs as objects are changed. This way you
> have your data as of 4am, but have all the changes that occured
> throughout the day should the server go own at 11pm.
> 
> In your serialization code you code also have synchoronization code
> between servers so that you can do load balancing and have hot-spares
> of services.
> 
> If some corruption of the data should also occur for whatever reason
> you can go a step-through of the transaction log up to the point data
> was still clean.
> 
> Just some thoughts; they may or may not be useful in your particular
> situation.

Ah.  Well, there's already a bunch of stuff built-in to Lisp that lets you
do all that too, starting with PRINT and READ.  (There's a reason
*print-readably*, *print-circle* and make-load-form exist.)

As for transaction logs, why do you need anything more than, say,:

(defmacro define-logged-function (name args &body body)
  `(defun ,name ,args
     (write-to-transaction-log (list ',name ,@args))
     ,@body))

To play back a log you just call LOAD.

It all still seems like a reinvented wheel to me.

E.
From: Arthur Lemmens
Subject: Re: CLOS and databases
Date: 
Message-ID: <opr44n6kfuk6vmsw@news.xs4all.nl>
Erann Gat wrote:

> I'm working on a simple object database built on top of a relational
> database.  My current design is to have a "storable" mixin class which
> defines two methods, STORE and RETRIEVE, which do the obvious things.
>
> A problem with this simple design is that it places a burden on the user
> to keep track of the relative states of the objects in memory and in the
> DB, and to decide when to STORE and RETRIEVE them.  It would be nice to
> make this transparent so that any reference to a slot of a STORABLE object
> would transparently synchronize to the DB.  I had envisioned implementing
> this using a :before method on the slot-value  and (setf slot-value)
> methods which would check to make sure everything was in sync.

SLOT-VALUE and (SETF SLOT-VALUE) are not generic functions, according to
the hyperspec.

> Is there a better way to do it?  Is this a job for the MOP?

Yes, it sounds like a classical example for the MOP. You could write
methods on SLOT-VALUE-USING-CLASS and (SETF SLOT-VALUE-USING-CLASS).
See e.g. "User-Level Language Crafting: Introducing the Metaobject Protocol"
by Andreas Paepcke for examples of how you could do this. Also, if I'm
not mistaken, the UncommonSQL library does some MOP hackery to achieve
something similar to what you want.

Arthur Lemmens
From: Pascal Costanza
Subject: Re: CLOS and databases
Date: 
Message-ID: <c3fr01$kpo$1@newsreader2.netcologne.de>
Erann Gat wrote:
> I'm working on a simple object database built on top of a relational
> database.  My current design is to have a "storable" mixin class which
> defines two methods, STORE and RETRIEVE, which do the obvious things.
> 
[...]

> Is there a better way to do it?  Is this a job for the MOP?

Yes, probably. Make sure to read the paper by Andreas Paepcke. It 
includes a detailed sketch how to add such a persistence layer by way of 
the MOP. Even if you don't want to use the MOP, it should give you the 
right ideas.


Pascal

-- 
1st European Lisp and Scheme Workshop
June 13 - Oslo, Norway - co-located with ECOOP 2004
http://www.cs.uni-bonn.de/~costanza/lisp-ecoop/
From: Erann Gat
Subject: Re: CLOS and databases
Date: 
Message-ID: <gNOSPAMat-1903041527450001@k-137-79-50-101.jpl.nasa.gov>
In article <············@newsreader2.netcologne.de>, Pascal Costanza
<········@web.de> wrote:

> Make sure to read the paper by Andreas Paepcke.

Which one?  He's written about ten million papers.

E.
From: Pascal Costanza
Subject: Re: CLOS and databases
Date: 
Message-ID: <c3g2np$3sj$1@newsreader2.netcologne.de>
Erann Gat wrote:

> In article <············@newsreader2.netcologne.de>, Pascal Costanza
> <········@web.de> wrote:
> 
>>Make sure to read the paper by Andreas Paepcke.
> 
> Which one?  He's written about ten million papers.

"User-level language crafting - Introducing the CLOS Metaobject 
Protocol", http://www-db.stanford.edu/~paepcke/shared-documents/mopintro.ps


Pascal

-- 
1st European Lisp and Scheme Workshop
June 13 - Oslo, Norway - co-located with ECOOP 2004
http://www.cs.uni-bonn.de/~costanza/lisp-ecoop/
From: André Thieme
Subject: Re: CLOS and databases
Date: 
Message-ID: <c3frg0$tl2$1@ulric.tng.de>
Erann Gat wrote:

> My goal here is not only to make something functional, but also to
> highlight the power of CLOS with something that will really knock the
> socks off the Java people, so I really want to do this the Right Way.

This last paragraph sounds interesting for me.
I am trying to collect as many examples as possible to see where Lisp is
in fact "better" than Java. As a Lisp beginner I did'nt really encounter
such situations. As soon I presented an experienced Java coder the Lisp
code he easily brought up very similar solutions - perhaps my examples
have been to easy so far.
But anyways, some people will ask why one first needs uuuullltra complex
problems so that Lisp has some slight advantages over Java (or Python)..
if it is so great one should find some advantages earlier.

Will you post your resulting code when you are done with your program?


Regards,
Andr�
--
From: Will Hartung
Subject: Re: CLOS and databases
Date: 
Message-ID: <c3fuld$26vl8s$1@ID-197644.news.uni-berlin.de>
"Andr� Thieme" <······································@justmail.de> wrote in
message ·················@ulric.tng.de...

> I am trying to collect as many examples as possible to see where Lisp is
> in fact "better" than Java. As a Lisp beginner I did'nt really encounter
> such situations. As soon I presented an experienced Java coder the Lisp
> code he easily brought up very similar solutions - perhaps my examples
> have been to easy so far.

Its always "easy" to counter simple examples with simple examples. "Oh, well
we just do xyz..."

> But anyways, some people will ask why one first needs uuuullltra complex
> problems so that Lisp has some slight advantages over Java (or Python)..
> if it is so great one should find some advantages earlier.

The reason is that you get to some point where the inertia of CLs
capabilities will break the Java Camels back.

Typically, all of the benefits of CL tend to be very incremental.

A "simple" example is "Aspect Oriented Programming".

Lisp already has some of these abilities "built in". A lot of Lisps have an
"advice" facility, (TRACE...) is a specialized example of that. Then you
have the before, after, and around methods of CLOS "for free". (And yes I
know there is more to AOP than advice and around methods.)

But even if it did not, by the nature of the system, they could be added
using standard mechanisms, including macros.

With Java, they had to write either a new compiler (AspectJ), or they have
to augment using XML, custom Classloaders, and byte code hacking (this is
how JBoss does their system). Neither one uses the Java Language itself to
implement AOP (yes, I know they were implemented in Java, but you don't
write AOP source in Java, you use AJ, or XML). The Java Language hit some
wall that they could not cross and at that point they hopped over and start
digging in and undermining the system from the outside in. As a language,
Java is simply not extensible. The JVM, of course, is quite flexible as
shown by assorted other languages that are not Java implemented on top of
it.

Lisp is extensible. Java is not. Not every task needs that extensibility,
but on the other hand, you don't need to implement large scale systems like
AOP to take advantage of the CL extensiblity. You can do it with little bits
on a daily basis. Layer upon layer, bit by bit. The beauty is that CL rises
to the level of abstraction necessary for the developer to be most
productive, which is different for each developer, and different for each
project. Java can only rise so high then stops, and it stops hard. All of a
sudden what would have been an incremental bit of abstraction in CL is now a
whole new project and tool suite for Java. CL "goes to 11".

A simple example of that is the new Java (1.5) has a new 'for' statement.
Yippee!

In CL those who want a new looping construct can create one and move on. A
simple example is the contentious IF* macro from Franz. No committees, no
papers, no votings, no new compilers, nothing. Need it? Use it, move on.
Your quality of life as a developer has just been bumped up an inch. One
less nit to pick and aggravate you when your day is going bad.

And to be fair, some don't value this property. It is safe to say that folks
may well value a standard Servlet container and binary platform portability
over being able to define a new 'for' loop or seemlessly implement AOP.

Regards,

Will Hartung
(·····@msoft.com)
From: Erann Gat
Subject: Re: CLOS and databases
Date: 
Message-ID: <gNOSPAMat-1903041533400001@k-137-79-50-101.jpl.nasa.gov>
In article <············@ulric.tng.de>, =?ISO-8859-1?Q?Andr=E9_Thieme?=
<······································@justmail.de> wrote:

> Will you post your resulting code when you are done with your program?

Yes, of course.  But that would be "if", not "when."  This is a
low-priority project.

E.
From: Edi Weitz
Subject: Re: CLOS and databases
Date: 
Message-ID: <m3ekroa2f5.fsf@bird.agharta.de>
On Fri, 19 Mar 2004 23:17:17 +0100, Andr� Thieme <······································@justmail.de> wrote:

> I am trying to collect as many examples as possible to see where
> Lisp is in fact "better" than Java. As a Lisp beginner I did'nt
> really encounter such situations. As soon I presented an experienced
> Java coder the Lisp code he easily brought up very similar solutions
> - perhaps my examples have been to easy so far.

What? The Java guys now have macros, a CLOS-like object system,
HANDLER-BIND, and UNWIND-PROTECT? I must have missed a couple of
memos...

BTW, do you want to impress other coders or to you want to code
yourself?

> But anyways, some people will ask why one first needs uuuullltra
> complex problems so that Lisp has some slight advantages over Java
> (or Python)..  if it is so great one should find some advantages
> earlier.

As long as you just hang around on Usenet and ask other people to
explain to you why Lisp is "better" you won't get anywhere. Read some
books, look at real code (I mean larger systems not two-liners), write
your own programs. Make sure you have at least a general understanding
about what each chapter of the CLHS is about. Then, after some months,
ask yourself again if you really need someone to hold your hand and
convince you that Lisp is the silver bullet.

Or just stay with Java and Python. Certainly everything that can be
done in Lisp can be done in these languages.

  <http://en.wikipedia.org/wiki/Turing-complete>

Edi.
From: André Thieme
Subject: Re: CLOS and databases
Date: 
Message-ID: <c3hfr4$14c$1@ulric.tng.de>
Edi Weitz wrote:
> wake up

Yes yes, you are right...
I ordered Norvigs "Paradigms of Artificial Intelligence Programming" and
should concentrate more on deepening my knowledge and do my analysis and
comparisons about languages later.


Andr�
--
From: Pascal Bourguignon
Subject: Re: CLOS and databases
Date: 
Message-ID: <87smg4fods.fsf@thalassa.informatimago.com>
Andr� Thieme <······································@justmail.de> writes:
> Erann Gat wrote:
> 
> > My goal here is not only to make something functional, but also to
> > highlight the power of CLOS with something that will really knock the
> > socks off the Java people, so I really want to do this the Right Way.
> 
> This last paragraph sounds interesting for me.
> I am trying to collect as many examples as possible to see where Lisp is
> in fact "better" than Java. As a Lisp beginner I did'nt really encounter
> such situations. As soon I presented an experienced Java coder the Lisp
> code he easily brought up very similar solutions - perhaps my examples
> have been to easy so far.
> But anyways, some people will ask why one first needs uuuullltra complex
> problems so that Lisp has some slight advantages over Java (or Python)..
> if it is so great one should find some advantages earlier.

Well, obviously Lisp evolved on complex problems!  If Lisp programmer
had been trying to solve easy problems for 50 years, you'd be writting:
    
    echo "Hello World!"

instead of all these parentheses!



-- 
__Pascal_Bourguignon__                     http://www.informatimago.com/
There is no worse tyranny than to force a man to pay for what he doesn't
want merely because you think it would be good for him.--Robert Heinlein
http://www.theadvocates.org/
From: Eric Smith
Subject: Re: CLOS and databases
Date: 
Message-ID: <1qjn509h0pa5cm3aka6i8nlq8n0hvtt1e9@4ax.com>
On Fri, 19 Mar 2004 11:17:51 -0800, ·········@jpl.nasa.gov (Erann Gat)
wrote:

>My goal here is not only to make something functional, but also to
>highlight the power of CLOS with something that will really knock the
>socks off the Java people, so I really want to do this the Right Way.

The Right Way is to use proxies.  Anything you want to do with a
stored object, such as use it in a calculation or whatever, should be
done by a function which takes a proxy of the stored object as an
argument.

The storage behavior of an object, e.g. whether it gets updated in the
database after every operation, whether it gets cached, etc., is
implemented as features of the proxies.  The program should be able to
tune the proxies, i.e. tell some proxies to use caching behavior and
others to not, etc.

This is the Right Way because it's at a higher level of abstraction
where the power of CLOS pays off better.  You don't have to concern
yourself constantly with low level details of storage behavior, but
only when actually designing the storage behavior and tuning it.

When thinking about proxies at the application logic level, you don't
even think of them as proxies, but rather as the stored objects
themselves.  The proxy is the object, for the purposes of the higher
level application code.

Also keep in mind that a stored object may actually occupy several
database tables.  You want to be thinking of the objects as objects,
not as database records.  The database records are the low level
details of the object, and should come to mind only when you need to
focus on such a low level of abstraction for the purpose of working on
the implementation of those low level details.

This doesn't establish Lisp as superior to Java for this purpose, but
it's the right direction to go, to get the full power of an object
database.  Once you start going in that direction, you will find
plenty of good uses for the power of CLOS.

--
My email address is ··········@ISP.net where Name is
eric, number is 9000, and ISP is earthlink.
From: Erann Gat
Subject: Re: CLOS and databases
Date: 
Message-ID: <gNOSPAMat-1903042348250001@192.168.1.51>
In article <··································@4ax.com>, Eric Smith
<·········@sig.txt> wrote:

> On Fri, 19 Mar 2004 11:17:51 -0800, ·········@jpl.nasa.gov (Erann Gat)
> wrote:
> 
> >My goal here is not only to make something functional, but also to
> >highlight the power of CLOS with something that will really knock the
> >socks off the Java people, so I really want to do this the Right Way.
> 
> The Right Way is to use proxies.

Actually, I think the Right Way is to make the objects *be* proxies for
themselves :-)  The idea is that an object that inherits from STORABLE
ends up having two states, one where its slots are known not to contain
correct data (you can think of this as the proxy state) and one where they
do (the non-proxy "real object" state).  If a reference is made to a slot
while it's in the proxy state, it updates itself from the DB
(transparently of course) which switches it into the non-proxy state, at
which point the calculation can proceed normally.

> Also keep in mind that a stored object may actually occupy several
> database tables.

Why?  I was planning on one table per class, with one column per class
instance slot, and a separate table for class slots (maybe -- I don't use
class slots much, so I haven't given this a whole lot of thought).

> You want to be thinking of the objects as objects,
> not as database records.  The database records are the low level
> details of the object, and should come to mind only when you need to
> focus on such a low level of abstraction for the purpose of working on
> the implementation of those low level details.

Yes, I agree, but I'm still curious why you think a single object might
span multiple tables.

E.
From: Eric Smith
Subject: Re: CLOS and databases
Date: 
Message-ID: <i67o50tstjfqpdl96rv9r4ghogcr98drt2@4ax.com>
On Fri, 19 Mar 2004 23:48:25 -0800, ·········@jpl.nasa.gov (Erann Gat)
wrote:

>Yes, I agree, but I'm still curious why you think a single object might
>span multiple tables.

One situation where that happens is when you're using a legacy
database and you want your program to deal with stored objects instead
of data tables, while an old mainframe in another room continues to
deal with the same data the way it always did.

Regardless, the point is to think of the stored objects as objects.
When you think in terms of slots or records, you're at a low level of
abstraction.  Instead of thinking in terms of getting data from the
stored object for an operation, think in terms of having the stored
object itself participate in the operation.

--
My email address is ··········@ISP.net where Name is
eric, Number is 9000, and ISP is earthlink.
From: Eric Smith
Subject: Re: CLOS and databases
Date: 
Message-ID: <7jao5017jkeve5v0lmojfdo8tglphp8al2@4ax.com>
On Fri, 19 Mar 2004 23:48:25 -0800, ·········@jpl.nasa.gov (Erann Gat)
wrote:

>Why?  I was planning on one table per class, with one column per class
>instance slot, and a separate table for class slots (maybe -- I don't use
>class slots much, so I haven't given this a whole lot of thought).

What if one of the slots has a list with up to a million items in it?
A relational database column is normally of a fixed size.

--
My email address is ··········@ISP.net where Name is
eric, Number is 9000, and ISP is earthlink.
From: Erann Gat
Subject: Re: CLOS and databases
Date: 
Message-ID: <gNOSPAMat-2003040915220001@192.168.1.51>
In article <··································@4ax.com>, Eric Smith
<·········@sig.txt> wrote:

> On Fri, 19 Mar 2004 23:48:25 -0800, ·········@jpl.nasa.gov (Erann Gat)
> wrote:
> 
> >Why?  I was planning on one table per class, with one column per class
> >instance slot, and a separate table for class slots (maybe -- I don't use
> >class slots much, so I haven't given this a whole lot of thought).
> 
> What if one of the slots has a list with up to a million items in it?
> A relational database column is normally of a fixed size.

That's a not an issue of having one object stored across multiple tables,
that an issue of how to store a cons cell in the database.  That is indeed
a very thorny issue, and one I haven't quite decided how to handle yet. 
But it seems to me to be an orthogonal issue to that of storing a single
object across multiple tables.

E.
From: Mario S. Mommer
Subject: Re: CLOS and databases
Date: 
Message-ID: <fzr7vnlq1a.fsf@germany.igpm.rwth-aachen.de>
·········@jpl.nasa.gov (Erann Gat) writes:
> In article <··································@4ax.com>, Eric Smith
> <·········@sig.txt> wrote:
> 
> > On Fri, 19 Mar 2004 11:17:51 -0800, ·········@jpl.nasa.gov (Erann Gat)
> > wrote:
> > 
> > >My goal here is not only to make something functional, but also to
> > >highlight the power of CLOS with something that will really knock the
> > >socks off the Java people, so I really want to do this the Right Way.
> > 
> > The Right Way is to use proxies.
> 
> Actually, I think the Right Way is to make the objects *be* proxies for
> themselves :-)  The idea is that an object that inherits from STORABLE
> ends up having two states, one where its slots are known not to contain
> correct data (you can think of this as the proxy state) and one where they
> do (the non-proxy "real object" state).  If a reference is made to a slot
> while it's in the proxy state, it updates itself from the DB
> (transparently of course) which switches it into the non-proxy state, at
> which point the calculation can proceed normally.

(:brainstorming-mode

        How about using kenny's cells for this? It sounds like exactly
        the kind of thing that they do well.)
From: Erann Gat
Subject: Re: CLOS and databases
Date: 
Message-ID: <gNOSPAMat-2003040913120001@192.168.1.51>
In article <··············@germany.igpm.rwth-aachen.de>, Mario S. Mommer
<········@yahoo.com> wrote:

> ·········@jpl.nasa.gov (Erann Gat) writes:
> > In article <··································@4ax.com>, Eric Smith
> > <·········@sig.txt> wrote:
> > 
> > > On Fri, 19 Mar 2004 11:17:51 -0800, ·········@jpl.nasa.gov (Erann Gat)
> > > wrote:
> > > 
> > > >My goal here is not only to make something functional, but also to
> > > >highlight the power of CLOS with something that will really knock the
> > > >socks off the Java people, so I really want to do this the Right Way.
> > > 
> > > The Right Way is to use proxies.
> > 
> > Actually, I think the Right Way is to make the objects *be* proxies for
> > themselves :-)  The idea is that an object that inherits from STORABLE
> > ends up having two states, one where its slots are known not to contain
> > correct data (you can think of this as the proxy state) and one where they
> > do (the non-proxy "real object" state).  If a reference is made to a slot
> > while it's in the proxy state, it updates itself from the DB
> > (transparently of course) which switches it into the non-proxy state, at
> > which point the calculation can proceed normally.
> 
> (:brainstorming-mode
> 
>         How about using kenny's cells for this? It sounds like exactly
>         the kind of thing that they do well.)

Could be.  I got the impression Cells did a lot more than that though,
that they were like a spreadsheet, computing a dependency graph for
expressions and propogating changes throughout the graph.  Not that that's
not a useful thing, but it seems a little heavyweight for what I'm trying
to do.  But I'll take a look.  Kenny, you want to weight in here?

E.
From: Kenny Tilton
Subject: Re: CLOS and databases
Date: 
Message-ID: <kfX6c.2629$DV6.706@twister.nyc.rr.com>
Mario S. Mommer wrote:

> ·········@jpl.nasa.gov (Erann Gat) writes:
> 
>>In article <··································@4ax.com>, Eric Smith
>><·········@sig.txt> wrote:
>>
>>
>>>On Fri, 19 Mar 2004 11:17:51 -0800, ·········@jpl.nasa.gov (Erann Gat)
>>>wrote:
>>>
>>>
>>>>My goal here is not only to make something functional, but also to
>>>>highlight the power of CLOS with something that will really knock the
>>>>socks off the Java people, so I really want to do this the Right Way.
>>>
>>>The Right Way is to use proxies.
>>
>>Actually, I think the Right Way is to make the objects *be* proxies for
>>themselves :-)  The idea is that an object that inherits from STORABLE
>>ends up having two states, one where its slots are known not to contain
>>correct data (you can think of this as the proxy state) and one where they
>>do (the non-proxy "real object" state).  If a reference is made to a slot
>>while it's in the proxy state, it updates itself from the DB
>>(transparently of course) which switches it into the non-proxy state, at
>>which point the calculation can proceed normally.
> 
> 
> (:brainstorming-mode
> 
>         How about using kenny's cells for this? It sounds like exactly
>         the kind of thing that they do well.)

I guess I could have jumped in sooner, on the OP where Erann wondered if 
a :before method on some my-slot-value method would be a good idea.

<jumpin>
The Cells /code/ might be useful as an example, since the functionality 
faces some of the same problems. And the answer to the original question 
about using a :before method on some slot-value wrapper is...

Yeah, but it is not a mere :before method on my-slot-value. 
my-slot-value and (setf my-slot-value) become huge little subsystems 
with all sorts of work to do before somewhere deep in the bowels of the 
code they actually invoke slot-value or its setf.

That's Cells, where the function name happens to be md-slot-value, "md" 
short for "model". As for a persistent ODB...

As a user of Franz's nifty AllegroStore I heard enough about the 
difficult issues in efficient, multi-user DBs (ODB or RDB) to have some 
confidence that the my-slot-value for that will also end up being its 
own little world. :before won't cut it, and there is no point in :around 
since you have to write an implementation wrapper anyway so it is 
already :around slot-value.

As for Cells itself, well, I had fun /marrying/ Cells and AllegroStore 
such that peristent instances interacted with each other and/or GUI 
views of them. As for implementing an ODB using them, I do not know 
enough about the issues to say much. But I sense the problems are 
orthogonal, and that PCells (persistent Cells) would be something again 
built atop some independent effort to solve all the hairy problems of 
robust, efficient, multi-user, networked DBs.
</jumpin>

kt


-- 
http://tilton-technology.com

Why Lisp? http://alu.cliki.net/RtL%20Highlight%20Film

Your Project Here! http://alu.cliki.net/Industry%20Application
From: james anderson
Subject: Re: CLOS and databases
Date: 
Message-ID: <405C5898.680AED14@setf.de>
Erann Gat wrote:
> 
> In article <··································@4ax.com>, Eric Smith
> <·········@sig.txt> wrote:
> 
> > On Fri, 19 Mar 2004 11:17:51 -0800, ·········@jpl.nasa.gov (Erann Gat)
> > wrote:
> >
> > >My goal here is not only to make something functional, but also to
> > >highlight the power of CLOS with something that will really knock the
> > >socks off the Java people, so I really want to do this the Right Way.
> >
> > The Right Way is to use proxies.
> 
> Actually, I think the Right Way is to make the objects *be* proxies for
> themselves :-)  The idea is that an object that inherits from STORABLE
> ends up having two states, one where its slots are known not to contain
> correct data (you can think of this as the proxy state) and one where they
> do (the non-proxy "real object" state).  If a reference is made to a slot
> while it's in the proxy state, it updates itself from the DB
> (transparently of course) which switches it into the non-proxy state, at
> which point the calculation can proceed normally.
> 

a third alternative is to flip the suggested proxy architecture around, to
offer low impedance access to the data model object and to interpose a proxy
between it and the database. this is the architecture which jdo realizes.

...
From: Alain Picard
Subject: Re: CLOS and databases
Date: 
Message-ID: <87oeqs0wm0.fsf@memetrics.com>
·········@jpl.nasa.gov (Erann Gat) writes:

>
> Yes, I agree, but I'm still curious why you think a single object might
> span multiple tables.

Inheritance.

-- 
It would be difficult to construe        Larry Wall, in  article
this as a feature.			 <·····················@netlabs.com>
From: Erann Gat
Subject: Re: CLOS and databases
Date: 
Message-ID: <gNOSPAMat-2003040911160001@192.168.1.51>
In article <··············@memetrics.com>, Alain Picard
<············@memetrics.com> wrote:

> ·········@jpl.nasa.gov (Erann Gat) writes:
> 
> >
> > Yes, I agree, but I'm still curious why you think a single object might
> > span multiple tables.
> 
> Inheritance.

Could you elaborate on that please?  It is not obvious to me why
inheritance would cause a single object to span multiple tables.

E.
From: Pascal Costanza
Subject: Re: CLOS and databases
Date: 
Message-ID: <c3i1ut$m8v$1@newsreader2.netcologne.de>
Erann Gat wrote:

>>Inheritance.
> 
> Could you elaborate on that please?  It is not obvious to me why
> inheritance would cause a single object to span multiple tables.

Assume a simple hierarchy.

(defclass c1 ()
   (x y))

(defclass c2 (c1)
   (z))

How do you store instances of such classes? There are basically the 
following schemes:

a) Create one table with columns x, y and z for both c1 and c2.

b) Create two tables c1 and c2.

c) Create one table with columns x and y for both c1 and c2. Another 
table delta-c2 only stores the additional z contained in c2 instances.

There is no clear winner here, because it all depends on how many 
instances of each class you expect to have, whether inserts / updates 
occur often, what information is frequently requested, whether you want 
to optimize for speed or for space, and so on...


Pascal

-- 
1st European Lisp and Scheme Workshop
June 13 - Oslo, Norway - co-located with ECOOP 2004
http://www.cs.uni-bonn.de/~costanza/lisp-ecoop/
From: Erann Gat
Subject: Re: CLOS and databases
Date: 
Message-ID: <gNOSPAMat-2003041103400001@192.168.1.51>
In article <············@newsreader2.netcologne.de>, Pascal Costanza
<········@web.de> wrote:

> Erann Gat wrote:
> 
> >>Inheritance.
> > 
> > Could you elaborate on that please?  It is not obvious to me why
> > inheritance would cause a single object to span multiple tables.
> 
> Assume a simple hierarchy.
> 
> (defclass c1 ()
>    (x y))
> 
> (defclass c2 (c1)
>    (z))
> 
> How do you store instances of such classes? There are basically the 
> following schemes:
> 
> a) Create one table with columns x, y and z for both c1 and c2.
> 
> b) Create two tables c1 and c2.
> 
> c) Create one table with columns x and y for both c1 and c2. Another 
> table delta-c2 only stores the additional z contained in c2 instances.
> 
> There is no clear winner here

Seems to me (b) is the clear winner.

>, because it all depends on how many 
> instances of each class you expect to have, whether inserts / updates 
> occur often, what information is frequently requested, whether you want 
> to optimize for speed or for space, and so on...

Sorry, but I don't see any realistic circumstances under which (a) or (c)
offer any substantial advantage.  (Remember, we're only talking about a
persistent store here.  We're not trying to optimize for anything other
than store and retrieve.)  Maybe I'm just being thick.  Could you describe
a scenario where (a) or (c) win over (b)?

E.
From: Peter Seibel
Subject: Re: CLOS and databases
Date: 
Message-ID: <m3ad2brwl7.fsf@javamonkey.com>
·········@jpl.nasa.gov (Erann Gat) writes:

> In article <············@newsreader2.netcologne.de>, Pascal Costanza
> <········@web.de> wrote:
>
>> Erann Gat wrote:
>> 
>> >>Inheritance.
>> > 
>> > Could you elaborate on that please?  It is not obvious to me why
>> > inheritance would cause a single object to span multiple tables.
>> 
>> Assume a simple hierarchy.
>> 
>> (defclass c1 ()
>>    (x y))
>> 
>> (defclass c2 (c1)
>>    (z))
>> 
>> How do you store instances of such classes? There are basically the 
>> following schemes:
>> 
>> a) Create one table with columns x, y and z for both c1 and c2.
>> 
>> b) Create two tables c1 and c2.
>> 
>> c) Create one table with columns x and y for both c1 and c2. Another 
>> table delta-c2 only stores the additional z contained in c2 instances.
>> 
>> There is no clear winner here
>
> Seems to me (b) is the clear winner.
>
>>, because it all depends on how many 
>> instances of each class you expect to have, whether inserts / updates 
>> occur often, what information is frequently requested, whether you want 
>> to optimize for speed or for space, and so on...
>
> Sorry, but I don't see any realistic circumstances under which (a) or (c)
> offer any substantial advantage.  (Remember, we're only talking about a
> persistent store here.  We're not trying to optimize for anything other
> than store and retrieve.)  Maybe I'm just being thick.  Could you describe
> a scenario where (a) or (c) win over (b)?

(a) select all instances of c1 (which includes all instances of c2)

(c) find the object ids of all c1 with slot x = 10 (which again includes instances of c2)

-Peter

-- 
Peter Seibel                                      ·····@javamonkey.com

         Lisp is the red pill. -- John Fraser, comp.lang.lisp
From: Erann Gat
Subject: Re: CLOS and databases
Date: 
Message-ID: <gNOSPAMat-2003041445160001@192.168.1.51>
In article <··············@javamonkey.com>, Peter Seibel
<·····@javamonkey.com> wrote:

> ·········@jpl.nasa.gov (Erann Gat) writes:
> 
> > In article <············@newsreader2.netcologne.de>, Pascal Costanza
> > <········@web.de> wrote:
> >
> >> Erann Gat wrote:
> >> 
> >> >>Inheritance.
> >> > 
> >> > Could you elaborate on that please?  It is not obvious to me why
> >> > inheritance would cause a single object to span multiple tables.
> >> 
> >> Assume a simple hierarchy.
> >> 
> >> (defclass c1 ()
> >>    (x y))
> >> 
> >> (defclass c2 (c1)
> >>    (z))
> >> 
> >> How do you store instances of such classes? There are basically the 
> >> following schemes:
> >> 
> >> a) Create one table with columns x, y and z for both c1 and c2.
> >> 
> >> b) Create two tables c1 and c2.
> >> 
> >> c) Create one table with columns x and y for both c1 and c2. Another 
> >> table delta-c2 only stores the additional z contained in c2 instances.
> >> 
> >> There is no clear winner here
> >
> > Seems to me (b) is the clear winner.
> >
> >>, because it all depends on how many 
> >> instances of each class you expect to have, whether inserts / updates 
> >> occur often, what information is frequently requested, whether you want 
> >> to optimize for speed or for space, and so on...
> >
> > Sorry, but I don't see any realistic circumstances under which (a) or (c)
> > offer any substantial advantage.  (Remember, we're only talking about a
> > persistent store here.  We're not trying to optimize for anything other
> > than store and retrieve.)  Maybe I'm just being thick.  Could you describe
> > a scenario where (a) or (c) win over (b)?
> 
> (a) select all instances of c1 (which includes all instances of c2)
> 
> (c) find the object ids of all c1 with slot x = 10 (which again includes
instances of c2)

Ah.  Well, both of these are beyond the scope of what I'm trying to do. 
Finding all the instances of a class is a facility that does not exist in
Common Lisp, and is orthogonal to the issue of building a persistent
object store.  (To say nothing of the fact that it is still not clear why
having single objects span multiple tables would be a win.  The only
advantage I see is that you could get all the info in a single query
instead of 1+N queries where N is the number of subclasses of the class of
interest.  Since N tends to be small in actual practice, the benefits of
the other designs still seem to me to be marginal at best.)

E.
From: Pascal Costanza
Subject: Re: CLOS and databases
Date: 
Message-ID: <c3ipr1$3m4$1@newsreader2.netcologne.de>
Erann Gat wrote:

>>a) Create one table with columns x, y and z for both c1 and c2.
>>
>>b) Create two tables c1 and c2.
>>
>>c) Create one table with columns x and y for both c1 and c2. Another 
>>table delta-c2 only stores the additional z contained in c2 instances.
>>
>>There is no clear winner here
> 
> Seems to me (b) is the clear winner.

This can only be the case if you have specific usage patterns in mind 
that we don't know about.

> Sorry, but I don't see any realistic circumstances under which (a) or (c)
> offer any substantial advantage.  (Remember, we're only talking about a
> persistent store here.  We're not trying to optimize for anything other
> than store and retrieve.)  Maybe I'm just being thick.  Could you describe
> a scenario where (a) or (c) win over (b)?

a) (change-class obj 'c2)

c) Many of the slots are unbound most of the time. (The AMOP book gives 
such an example as a motivation for hashtable-based classes.)

If b) is the clear winner in your case that's of course fine. However, 
you might also want to be prepared for questions wrt alternative 
object<->table mappings from the people you present your solution to. 
(Don't know what the actual setting is, though.)


Pascal

-- 
1st European Lisp and Scheme Workshop
June 13 - Oslo, Norway - co-located with ECOOP 2004
http://www.cs.uni-bonn.de/~costanza/lisp-ecoop/
From: Erann Gat
Subject: Re: CLOS and databases
Date: 
Message-ID: <gNOSPAMat-2003041936490001@192.168.1.51>
In article <············@newsreader2.netcologne.de>, Pascal Costanza
<········@web.de> wrote:

> Erann Gat wrote:
> 
> >>a) Create one table with columns x, y and z for both c1 and c2.
> >>
> >>b) Create two tables c1 and c2.
> >>
> >>c) Create one table with columns x and y for both c1 and c2. Another 
> >>table delta-c2 only stores the additional z contained in c2 instances.
> >>
> >>There is no clear winner here
> > 
> > Seems to me (b) is the clear winner.
> 
> This can only be the case if you have specific usage patterns in mind 
> that we don't know about.

That's likely true.  Like someone else said, I probably want things that I
don't know that I want :-)

> > Sorry, but I don't see any realistic circumstances under which (a) or (c)
> > offer any substantial advantage.  (Remember, we're only talking about a
> > persistent store here.  We're not trying to optimize for anything other
> > than store and retrieve.)  Maybe I'm just being thick.  Could you describe
> > a scenario where (a) or (c) win over (b)?
> 
> a) (change-class obj 'c2)

It seems to me that you're making the tacit assumption that obj is a C1. 
Be that as it may, in the worst case this would cause the object to move
from whatever table it's in to the C2 table.  That's not an expensive
operation.

> c) Many of the slots are unbound most of the time. (The AMOP book gives 
> such an example as a motivation for hashtable-based classes.)

So?  Are you trying to save disk space?  In an age where 100 GB hard
drives are commonplace that seems like the height of premature
optimization.


> If b) is the clear winner in your case that's of course fine. However, 
> you might also want to be prepared for questions wrt alternative 
> object<->table mappings from the people you present your solution to. 
> (Don't know what the actual setting is, though.)

I'm not trying to pick a fight here.  I'm genuinely trying to understand
why you think that (a) and (c) can sometimes be big wins.  I just don't
see it.

E.
From: Patrick May
Subject: Re: CLOS and databases
Date: 
Message-ID: <m1znaagum4.fsf@localhost.localdomain>
·········@jpl.nasa.gov (Erann Gat) writes:
[ . . . ]
> I'm not trying to pick a fight here.  I'm genuinely trying to
> understand why you think that (a) and (c) can sometimes be big wins.
> I just don't see it.

     I've been following this thread with some interest because I've
had to solve this problem in both C++ and Java (yes, I realize that my
karmic burden is heavy).  Just to stir the pot a bit, one of the
requirements of the toolkits I developed was compatibility with legacy
database schemas.  Object state could be spread over a number of
tables and one table could hold part of the state of multiple types.
Do you have this requirement?  Do you anticipate having it in the
future?  Is there any reason for your design not to allow it?

Regards,

Patrick

------------------------------------------------------------------------
S P Engineering, Inc.    | The experts in large scale distributed OO
                         | systems design and implementation.
          ···@spe.com    | (C++, Java, ObjectStore, Oracle, CORBA, UML)
From: Erann Gat
Subject: Re: CLOS and databases
Date: 
Message-ID: <gNOSPAMat-2103040816330001@192.168.1.51>
In article <··············@localhost.localdomain>, Patrick May
<···@spe.com> wrote:

> ·········@jpl.nasa.gov (Erann Gat) writes:
> [ . . . ]
> > I'm not trying to pick a fight here.  I'm genuinely trying to
> > understand why you think that (a) and (c) can sometimes be big wins.
> > I just don't see it.
> 
>      I've been following this thread with some interest because I've
> had to solve this problem in both C++ and Java (yes, I realize that my
> karmic burden is heavy).  Just to stir the pot a bit, one of the
> requirements of the toolkits I developed was compatibility with legacy
> database schemas.  Object state could be spread over a number of
> tables and one table could hold part of the state of multiple types.
> Do you have this requirement?

No.

>  Do you anticipate having it in the future?

No.

> Is there any reason for your design not to allow it?

Yes.  This is a persistent object store that happens to use a relational
database in the implementation.  It is not intended to be a general OO
interface to a relational database.  I am not out to reinvent commonSQL. 
I want to keep this lightweight.

Because this is an object store, I want to preserve object identity as
much as possible.  For example, if X is a list, I want it to be the case
that:

(eq (cdr (retrieve (store x))) (retrieve (store (cdr x))))  --> T

This requires me to impose a rigid design on the database schema I'm using
to store objects.  I'm essentially building something that looks like a
Lisp heap on disk.  Nearly everything is an integer foreign key (which is
to say, a pointer), and to make it work the keys all have to conform to
certain conventions that any legacy DB is extremely unlilkely to adhere
to.

That said, I do have a simple table->object mapping that works on any
table and simply presents each row as an object with a slot for each
column.  All the values are assumed to be atomic types.  If you want to
create an object mapping across multiple tables you can do that by using a
database that provides views.

E.
From: Pascal Costanza
Subject: Re: CLOS and databases
Date: 
Message-ID: <c3k6ad$keq$1@newsreader2.netcologne.de>
Erann Gat wrote:

> So?  Are you trying to save disk space?  In an age where 100 GB hard
> drives are commonplace that seems like the height of premature
> optimization.

"640K ought to be enough for everyone." - Bill Gates

;)


Pascal

P.S.: I am only giving you second-hand knowledge. I am not a database 
expert myself. What seems to be an important factor in large databases 
is that schema evolution is very expensive, so it's hard to tune a 
database after you have identified a bottleneck. So it seems to be 
worthwhile to have a good idea what your usage patterns are going to be. 
My conclusion would rather be to think hard about avoiding a relational 
database as long as possible, and for example store information as 
s-expressions in text files instead.

-- 
1st European Lisp and Scheme Workshop
June 13 - Oslo, Norway - co-located with ECOOP 2004
http://www.cs.uni-bonn.de/~costanza/lisp-ecoop/
From: Pascal Bourguignon
Subject: Re: CLOS and databases
Date: 
Message-ID: <87ad2affkf.fsf@thalassa.informatimago.com>
Pascal Costanza <········@web.de> writes:
> P.S.: I am only giving you second-hand knowledge. I am not a database
> expert myself. What seems to be an important factor in large databases
> is that schema evolution is very expensive, so it's hard to tune a
> database after you have identified a bottleneck. So it seems to be
> worthwhile to have a good idea what your usage patterns are going to
> be. My conclusion would rather be to think hard about avoiding a
> relational database as long as possible, and for example store
> information as s-expressions in text files instead.

Right.  Or if you really have to put your objects into a RDBMS, store
them in BLOBS, and only add a few "key" columns for indexing.

-- 
__Pascal_Bourguignon__                     http://www.informatimago.com/
There is no worse tyranny than to force a man to pay for what he doesn't
want merely because you think it would be good for him.--Robert Heinlein
http://www.theadvocates.org/
From: Pascal Bourguignon
Subject: Re: CLOS and databases
Date: 
Message-ID: <87ekrmffnm.fsf@thalassa.informatimago.com>
·········@jpl.nasa.gov (Erann Gat) writes:
> So?  Are you trying to save disk space?  In an age where 100 GB hard
> drives are commonplace that seems like the height of premature
> optimization.

My disks, be them 10 MB, 10 GB or 160 GB, seem to always be 99% full...  :-)

-- 
__Pascal_Bourguignon__                     http://www.informatimago.com/
There is no worse tyranny than to force a man to pay for what he doesn't
want merely because you think it would be good for him.--Robert Heinlein
http://www.theadvocates.org/
From: David Magda
Subject: Re: CLOS and databases
Date: 
Message-ID: <86y8purl9k.fsf@number6.magda.ca>
Pascal Bourguignon <····@thalassa.informatimago.com> writes:

> ·········@jpl.nasa.gov (Erann Gat) writes:
> > So?  Are you trying to save disk space?  In an age where 100 GB
> > hard drives are commonplace that seems like the height of
> > premature optimization.
> 
> My disks, be them 10 MB, 10 GB or 160 GB, seem to always be 99%
> full...  :-)

Parkinson's Law of Data:

    Data expands to fill the space available for storage.

    http://www.faqs.org/docs/jargon/P/Parkinson's-Law-of-Data.html

Works for automobiles and the expansion of highways/roads (especially
evident in California I think).


Parkinson's Law:

    Work expands so as to fill the time available for its completion.

    http://www.heretical.com/miscella/parkinsl.html


He had several others: http://www.globalideasbank.org/socinv/SIC-117.HTML

-- 
David Magda <dmagda at ee.ryerson.ca>, http://www.magda.ca/
Because the innovator has for enemies all those who have done well under
the old conditions, and lukewarm defenders in those who may do well 
under the new. -- Niccolo Machiavelli, _The Prince_, Chapter VI
From: Karsten Poeck
Subject: Re: CLOS and databases
Date: 
Message-ID: <ln07c.1898$Rc.208571@news-reader.eresmas.com>
"Erann Gat" <·········@jpl.nasa.gov> wrote in message
·······························@192.168.1.51...
> In article <··············@memetrics.com>, Alain Picard
> <············@memetrics.com> wrote:
>
> > ·········@jpl.nasa.gov (Erann Gat) writes:
> >
> > >
> > > Yes, I agree, but I'm still curious why you think a single object
might
> > > span multiple tables.
> >
> > Inheritance.
>
> Could you elaborate on that please?  It is not obvious to me why
> inheritance would cause a single object to span multiple tables.
>
> E.


Assume you have a class partner with slots a b c
This class is subclassed  by the classes person with additional slot d and
company with additional slot e.

One possible scheme for persistence is to use three database tables
1 partner with columns a, b and c (lets assume that a is the pkey)
2 person with  a and d
3 company with a and e

An instance of person or company obviously spans 2 tables.

If have also seen that people model this case just with one table
partner
with columns a, b, c, d ,e and a technical column f to indicate to the
corresponding class

A third solution uses two tables person and company (assuming that partner
is abstract)
but this has the disadvatage that all columns of partner have to be
duplicated in the tables person and company

saludos

Karsten
From: Erann Gat
Subject: Re: CLOS and databases
Date: 
Message-ID: <gNOSPAMat-2003041105100001@192.168.1.51>
In article <····················@news-reader.eresmas.com>, "Karsten Poeck"
<························@wanadoo.es> wrote:

> A third solution uses two tables person and company (assuming that partner
> is abstract)
> but this has the disadvatage that all columns of partner have to be
> duplicated in the tables person and company

Why is that a disadvantage?

E.
From: Rob Warnock
Subject: Re: CLOS and databases
Date: 
Message-ID: <pPCdnfE3mfHhMMHd3czS-w@speakeasy.net>
Erann Gat <·········@jpl.nasa.gov> wrote:
+---------------
| "Karsten Poeck" <························@wanadoo.es> wrote:
| > A third solution uses two tables person and company (assuming that partner
| > is abstract)
| > but this has the disadvatage that all columns of partner have to be
| > duplicated in the tables person and company
| 
| Why is that a disadvantage?
+---------------

Think about the implications of a superclass with slots with class
allocation. If you duplicate those slots in multiple subclass tables,
you immediately run up against a consistency-constraint problem.

It seems to me that if you're look at the data with an "Entity/Relationship"
viewpoint (E-R modelling), than the the entities work o.k. as objects,
but only for a completely flat class hierarchy. The M:N relationships
don't at all (and 1:N and N:1 relationships are just subsets of those).

Try this concrete example: What would your object hierarchy have to
look like so that when a company changed the location of one of its
offices ("Branch #N"), all of the work addresses for employees who
work at that branch automatically change to match the new location?
Classically, in a 3NF database that information is *not* stored in
the employee record, but in a separate "company/branch#/address" table.
(Sound like a superclass with class-allocated slots?)


-Rob

-----
Rob Warnock			<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: Erann Gat
Subject: Re: CLOS and databases
Date: 
Message-ID: <gNOSPAMat-2003041312320001@192.168.1.51>
In article <······················@speakeasy.net>, ····@rpw3.org (Rob
Warnock) wrote:

> Erann Gat <·········@jpl.nasa.gov> wrote:
> +---------------
> | "Karsten Poeck" <························@wanadoo.es> wrote:
> | > A third solution uses two tables person and company (assuming that partner
> | > is abstract)
> | > but this has the disadvatage that all columns of partner have to be
> | > duplicated in the tables person and company
> | 
> | Why is that a disadvantage?
> +---------------
> 
> Think about the implications of a superclass with slots with class
> allocation. If you duplicate those slots in multiple subclass tables,
> you immediately run up against a consistency-constraint problem.

The issue of class-allocated slots seems to me completely orthogonal to
the issue of inheritance.  Obviously you want to store the class-allocated
slots on a per-class basis, not on a per-instance basis, but that's true
whether or not the class inherits or is inherited from.

So I guess I'll buy class-allocated slots as an example of where an
instance is stored in multiple (two) tables.  (I don't actually use
class-allocated slots myself.  They don't provide any useful functionality
IMO.  If someone wants to contest that they should probably start a new
thread.)

> It seems to me that if you're look at the data with an "Entity/Relationship"
> viewpoint (E-R modelling), than the the entities work o.k. as objects,
> but only for a completely flat class hierarchy. The M:N relationships
> don't at all (and 1:N and N:1 relationships are just subsets of those).
> 
> Try this concrete example: What would your object hierarchy have to
> look like so that when a company changed the location of one of its
> offices ("Branch #N"), all of the work addresses for employees who
> work at that branch automatically change to match the new location?
> Classically, in a 3NF database that information is *not* stored in
> the employee record, but in a separate "company/branch#/address" table.
> (Sound like a superclass with class-allocated slots?)

I've never heard of a company changing the location of one of its
offices.  That would require some major structural engineering.  I have
heard of companies moving all the employees at one work location to a
different work location, but that is not at all the same thing.

But be that as it may, to me that sounds like an instance slot in the
employee class that contains a work-location object, which in turn
contains a work address.  Many employees would probably share the same (in
the sense of eq) work location.

E.
From: Joe Marshall
Subject: Re: CLOS and databases
Date: 
Message-ID: <brmqfzx1.fsf@comcast.net>
·········@jpl.nasa.gov (Erann Gat) writes:

> I've never heard of a company changing the location of one of its
> offices.  That would require some major structural engineering.  I have
> heard of companies moving all the employees at one work location to a
> different work location, but that is not at all the same thing.

I thought you lived in California.  I understand that offices can move
quite a bit around there.

-- 
~jrm
From: Erann Gat
Subject: Re: CLOS and databases
Date: 
Message-ID: <gNOSPAMat-2103040750380001@192.168.1.51>
In article <············@comcast.net>, Joe Marshall
<·············@comcast.net> wrote:

> ·········@jpl.nasa.gov (Erann Gat) writes:
> 
> > I've never heard of a company changing the location of one of its
> > offices.  That would require some major structural engineering.  I have
> > heard of companies moving all the employees at one work location to a
> > different work location, but that is not at all the same thing.
> 
> I thought you lived in California.  I understand that offices can move
> quite a bit around there.

Touche :-)

E.
From: Ray Fink
Subject: Re: CLOS and databases
Date: 
Message-ID: <uoeqo3e6d.fsf@cableone.THIS_PART_IS_BOGUS.net>
Alain Picard <············@memetrics.com> writes:

> ·········@jpl.nasa.gov (Erann Gat) writes:
> 
> >
> > Yes, I agree, but I'm still curious why you think a single object might
> > span multiple tables.
> 
> Inheritance.

Or attribute lists (for lack of a better term at the moment).  
Consider an object with a slot whose value is a list of properties, that
don't deserve to be objects in their own right.  In the relational world, 
those properties are going to be in a child table. 

I found this child-table business to be the most annoying part of implementing
a relational data store for a CLOS application.  Not insurmountable, just
annoying...

-- Ray
From: Erann Gat
Subject: Re: CLOS and databases
Date: 
Message-ID: <gNOSPAMat-2203041124030001@k-137-79-50-101.jpl.nasa.gov>
In article <·············@cableone.THIS_PART_IS_BOGUS.net>, Ray Fink
<···@cableone.THIS_PART_IS_BOGUS.net> wrote:

> Alain Picard <············@memetrics.com> writes:
> 
> > ·········@jpl.nasa.gov (Erann Gat) writes:
> > 
> > >
> > > Yes, I agree, but I'm still curious why you think a single object might
> > > span multiple tables.
> > 
> > Inheritance.
> 
> Or attribute lists (for lack of a better term at the moment).  
> Consider an object with a slot whose value is a list of properties, that
> don't deserve to be objects in their own right.  In the relational world, 
> those properties are going to be in a child table. 

I would not consider this to be a single object that spans multiple tables
but rather an object with a slot whose value is a different object of a
different type, which is therefore unsurprisingly stored in a different
table.

> I found this child-table business to be the most annoying part of implementing
> a relational data store for a CLOS application.  Not insurmountable, just
> annoying...

What did you find annoying about it?  Is it just writing out all the WHERE
clauses in the query statements, or was it something else?

E.
From: Ray Fink
Subject: Re: CLOS and databases
Date: 
Message-ID: <uk71bo14p.fsf@cableone.THIS_PART_IS_BOGUS.net>
·········@jpl.nasa.gov (Erann Gat) writes:
> In article <·············@cableone.THIS_PART_IS_BOGUS.net>, Ray Fink
> <···@cableone.THIS_PART_IS_BOGUS.net> wrote:
...snipped..
> > Or attribute lists (for lack of a better term at the moment).  
> > Consider an object with a slot whose value is a list of properties, that
> > don't deserve to be objects in their own right.  In the relational world, 
> > those properties are going to be in a child table. 
> 
> I would not consider this to be a single object that spans multiple tables
> but rather an object with a slot whose value is a different object of a
> different type, which is therefore unsurprisingly stored in a different
> table.

Fair enough.  But do note this other object (the list) is itself a compound
object, constituting multiple rows in another table.

> > I found this child-table business to be the most annoying part of implementing
> > a relational data store for a CLOS application.  Not insurmountable, just
> > annoying...
> 
> What did you find annoying about it?  Is it just writing out all the WHERE
> clauses in the query statements, or was it something else?

Annoying (1) in the sense of tedious, WHERE clauses and such, and 
(2) that I felt that my implementation didn't abstract away enough of 
those details.  The implementation of the base class was about 
1200 lines of code (including comments and whitespace), client classes
had to provide another ten or twenty lines of code for each slot that
referenced a child table, including defining the SELECT statements, in
addition to declarations for the relational table name and slot-to-field
mapping.

On a positive note, that code has been in daily production use
(with small transaction volumes) since 1992, and working quite nicely.

-- Ray
From: Marco Antoniotti
Subject: Re: CLOS and databases
Date: 
Message-ID: <yx_7c.121$IJ5.108926@typhoon.nyu.edu>
For tangential reasons, somebody at my lab has been looking into 
"object-relational mapping" technology. We looked mostly at Java stuff. 
  Things like Hibernate, Castor and CocoBase.

The mapping itself is tricky on a conceptual level that goes beyond 
CLOS.  A CLOS based mapping would be nice to have.

Cheers

Marco







Ray Fink wrote:

> Alain Picard <············@memetrics.com> writes:
> 
> 
>>·········@jpl.nasa.gov (Erann Gat) writes:
>>
>>
>>>Yes, I agree, but I'm still curious why you think a single object might
>>>span multiple tables.
>>
>>Inheritance.
> 
> 
> Or attribute lists (for lack of a better term at the moment).  
> Consider an object with a slot whose value is a list of properties, that
> don't deserve to be objects in their own right.  In the relational world, 
> those properties are going to be in a child table. 
> 
> I found this child-table business to be the most annoying part of implementing
> a relational data store for a CLOS application.  Not insurmountable, just
> annoying...
> 
> -- Ray
> 
From: Pascal Bourguignon
Subject: Re: CLOS and databases
Date: 
Message-ID: <87hdwfbbrx.fsf@thalassa.informatimago.com>
Marco Antoniotti <·······@cs.nyu.edu> writes:

> For tangential reasons, somebody at my lab has been looking into
> "object-relational mapping" technology. We looked mostly at Java
> stuff. Things like Hibernate, Castor and CocoBase.
> 
> The mapping itself is tricky on a conceptual level that goes beyond
> CLOS.  A CLOS based mapping would be nice to have.

openmcl + (clos <-> Objective-C in latest version) + MacOSX WebObject.

-- 
__Pascal_Bourguignon__                     http://www.informatimago.com/
There is no worse tyranny than to force a man to pay for what he doesn't
want merely because you think it would be good for him.--Robert Heinlein
http://www.theadvocates.org/
From: Alain Picard
Subject: Re: CLOS and databases
Date: 
Message-ID: <871xnjcgm6.fsf@memetrics.com>
Ray Fink <···@cableone.THIS_PART_IS_BOGUS.net> writes:

> Or attribute lists (for lack of a better term at the moment).  
> Consider an object with a slot whose value is a list of properties, that
> don't deserve to be objects in their own right.  In the relational world, 
> those properties are going to be in a child table. 

If the objects in the list are all "simple", what I did was
to create a "db-huge-lisp-object" table type, where I could
stuff any lisp object which supports a READ/WRITE operation.
Thus you could do things like
 (setf (some-slot my-persistent-obj) (list 1 2 3))
for example.

Is that what you meant?

Alternately, if you contain a list of other persistent objects,
all of some unified superclass, you could do

 (make-instance* owner 'sub-foo-1 :initargs...)
 (make-instance* owner 'sub-foo-2 :initargs...)
 (make-instance* owner 'sub-foo-3 :initargs...)

and later, in a new image, say

(foos owner)
=>  (#<sub-foo-1 "Joe"> #<sub-foo-2 "Sam"> #<sub-foo-2 "Sally">)

This requires objects to "transmogrify" from their superclass
into their real (final) class at time of instantiation.

This is part of the "magic I needed but didn't know I needed"
when I started writing this whole mess.  :-)
From: Ray Fink
Subject: Re: CLOS and databases
Date: 
Message-ID: <u3c7x2zcq.fsf@cableone.THIS_PART_IS_BOGUS.net>
Alain Picard <············@memetrics.com> writes:

> Ray Fink <···@cableone.THIS_PART_IS_BOGUS.net> writes:
> 
> > Or attribute lists (for lack of a better term at the moment).  
> > Consider an object with a slot whose value is a list of properties, that
> > don't deserve to be objects in their own right.  In the relational world, 
> > those properties are going to be in a child table. 
> 
> If the objects in the list are all "simple", what I did was
> to create a "db-huge-lisp-object" table type, where I could
> stuff any lisp object which supports a READ/WRITE operation.
> Thus you could do things like
>  (setf (some-slot my-persistent-obj) (list 1 2 3))
> for example.
> 
> Is that what you meant?

Not quite.  I meant working with a relational database, normalized,
specifically so the data from the Lisp application would be 
accessible to conventional desktop tools (e.g. ODBC to Excel, Access, 
etc).  Thus it was necessary to store data in a format that could be 
understood _and_ manipulated by non-Lisp applications... plain old 
NUMBER and VARCHAR2 and other "plain vanilla" SQL datatypes.  So
to use your example above, there are three records in the child table
(SOME_SLOT), each with a foreign key column that leads back to 
the parent object.
  
> Alternately, if you contain a list of other persistent objects,
> all of some unified superclass, you could do
> 
>  (make-instance* owner 'sub-foo-1 :initargs...)
>  (make-instance* owner 'sub-foo-2 :initargs...)
>  (make-instance* owner 'sub-foo-3 :initargs...)
> 
> and later, in a new image, say
> 
> (foos owner)
> =>  (#<sub-foo-1 "Joe"> #<sub-foo-2 "Sam"> #<sub-foo-2 "Sally">)
> 
> This requires objects to "transmogrify" from their superclass
> into their real (final) class at time of instantiation.
> 
> This is part of the "magic I needed but didn't know I needed"
> when I started writing this whole mess.  :-)
From: Pascal Costanza
Subject: Re: CLOS and databases
Date: 
Message-ID: <c3htgi$e16$1@newsreader2.netcologne.de>
Erann Gat wrote:

> I'm working on a simple object database built on top of a relational
> database.  My current design is to have a "storable" mixin class which
> defines two methods, STORE and RETRIEVE, which do the obvious things.
[...]

> Is there a better way to do it?  Is this a job for the MOP?

Another hint, taking into account that you are using MCL: It's true that 
MCL doesn't support the whole MOP, but IIRC the introspection stuff is 
pretty much complete. You could traverse the class hierarchy and find 
all accessor methods, and then just define before/after/around methods 
on those and require that accesses do not go through SLOT-VALUE for 
those classes. (Accessor methods for standard classes are required to be 
instances of STANDARD-ACCESSOR-METHOD.)

> My goal here is not only to make something functional, but also to
> highlight the power of CLOS with something that will really knock the
> socks off the Java people, so I really want to do this the Right Way.

Another completely different approach would be to use the object 
prevalence framework at http://homepage.mac.com/svc/prevalence/readme.html


Pascal

-- 
1st European Lisp and Scheme Workshop
June 13 - Oslo, Norway - co-located with ECOOP 2004
http://www.cs.uni-bonn.de/~costanza/lisp-ecoop/
From: Erann Gat
Subject: Re: CLOS and databases
Date: 
Message-ID: <gNOSPAMat-2003040930350001@192.168.1.51>
In article <············@newsreader2.netcologne.de>, Pascal Costanza
<········@web.de> wrote:

> Another completely different approach would be to use the object 
> prevalence framework at http://homepage.mac.com/svc/prevalence/readme.html

Thanks for the pointer.  This seems very similar to what I'm doing except
that I'm going to an RDB instead of XML (which are actually very similar
if you think about it.)

E.
From: Pete Kirkham
Subject: Re: CLOS and databases
Date: 
Message-ID: <405c924d$0$6548$cc9e4d1f@news-text.dial.pipex.com>
Erann Gat wrote:
> My goal here is not only to make something functional, but also to
> highlight the power of CLOS with something that will really knock the
> socks off the Java people, so I really want to do this the Right Way.
As a lisp liking Java person, here are the points you need to address to 
de-sock a Java-head:

Remember in your comparison that the 'Java way' is not REP but making 
the program from source files with a build utility, often integrated 
with an IDE.

In Java, there is no MOP built into the language spec. (There again, in 
ANSI common lisp, ditto). There is, instead, a mechanism for specifying 
metadata about packages, classes, fields, and methods, called javadoc. 
Javadocs consist of a descriptive string, and certain attribute tags. 
This metadata is processed by a separate processor to the compiler, as 
part of the build process for the project. Sun provides mechanisms and a 
parser for people to extend this metadata by adding their own attributes.

In Java, there is no 'slot-accessor'. Inside a class, the fields are 
accessed using the field access primitives. Outside, mutable fields 
should be accessed using accessor function pairs. This isn't enforced by 
the language, but strongly encouraged by every Java text I've seen.

For example, the class
(defclass foo () ( (foo :type integer) ) )

Would be written in Java as:

class Foo {
   int foo;

   public int getFoo () {
     return this.foo;
   }

   public void setFoo (int foo) {
     this.foo = foo;
   }
}

Whereas the version with public field access:
class Foo {
  public int foo;
}

Would be used where a struct would be in C, rather than as a full blown 
class.

As part of the Java build process, tools such as AspectJ, XDoclet and 
the many DB binding tools process either the code before the javac 
compiler, or the byte code after. XDoclet uses the Sun-sanctioned 
metadata mechanism, for example to using the hibernate DB mechanism the 
attribute:
/**
  * @hibernate.class
  *  table="FOO"
  */
Is added to the jdoc, and the doclet processor called as part of the 
build process. This adds the function calls to the source code before or 
after the property accessors to ensure the

Javadocs are the mechanism where metadata for the elements that are 
available in the MOP is stored in Java source code for compile-time 
processing. There is a separate mechanism, the reflection API, for 
getting metadata at runtime.

After the ·@' <java-legal-name>, the syntax is not restricted by the 
doclet spec, instead the text to the next @ is returned as a string. 
This is to be changed in version 1.5 of java, where user defined @tags 
are allowed in the source code proper, and will be available via the 
reflection API at runtime.

The processors that process the compile-time metadata are not specified 
in the language, but Sun provides a framework to add them to. The build 
process itself is not specified in the language, but one build tool, 
Ant, is ubiquitous.

[java head off: It is a less than good thing that the only extension 
mechanism in java (version<=1.4) is by adding to the jdocs, and that 
jdoc sections are tagged in a manner such that the javac compiler 
re-uses the /* to ignore, allowing people confuse them with comments.]

Using a freely available DB binding framework (hibernate), the 
'standard' java build tool (Ant), the Java language's metadata mechanism 
(doctags) and an implementation of a doctag processor (XDoclet), what is 
needed to implement the functionality in Java is
- one XML element added to the build script to invoke the metadata 
processor.
- two lines of metadata added per class to specify the database table.


That is what is the 'competition' is for this kind of functionality in a 
typical Java development environment. Much as I like the REP loop, I 
don't believe that for commercial scale development lispers don't use 
build scripts. The difference being that the scripts are in the same 
language, and the metadata is in the same syntax, and available at 
runtime in a consistent manner.

Ultimately, as frameworks for binding Java classes to DBs are at an 
advanced state of functionality, and have all the transaction queuing 
etc. sorted, I think the case for lisp in this comes down to:
  - one step compile has real advantage over separate build steps in a 
script
  - one syntax for metadata, build script and program better than 
distinct syntaxes

and maybe:
  Metadata available in consistent manner at runtime

Though for the simple 'persist to db' cases the metadata isn't required.

As for 'ease of use to a typical programmer who can use the available 
tools', 'number of lines of code to do it', or 'impact when retro 
fitting to existing app' don't seem to be where you can gain in this use 
case.


Pete
From: Erann Gat
Subject: Re: CLOS and databases
Date: 
Message-ID: <gNOSPAMat-2003041124540001@192.168.1.51>
In article <························@news-text.dial.pipex.com>, Pete
Kirkham <·················@cafemosaic.co.uk> wrote:

> Erann Gat wrote:
> > My goal here is not only to make something functional, but also to
> > highlight the power of CLOS with something that will really knock the
> > socks off the Java people, so I really want to do this the Right Way.
> As a lisp liking Java person, here are the points you need to address to 
> de-sock a Java-head:
> 
> Remember in your comparison that the 'Java way' is not REP but making 
> the program from source files with a build utility, often integrated 
> with an IDE.

Yes, there is a long-standing tension between two fundamentally different
philosophies about how code should be written.  The first philosophy is
that you should have two distinct phases, design and coding, and that
design should be complete before coding begins.  The second is that design
and coding should be continually blended in what is often termed
"exploratory programming" or "rapid prototyping".  The argument against
the design-first-code-second philosophy is that requirement creep and
other nasty surprises are inevitable, and that these are responsible for
the chronic schedule and budget overruns that are notorious in the
industry.  The argument against exploratory programming is that if you
don't plan ahead you are essentially hill-climbing and will inevitably end
up with a sub-optimal solution.  This was all discussed at length here a
few months ago.

This becomes a dichotomy only if you believe that programmers are by
nature so undisciplined that the only way to keep from falling into the
hill-climbing trap is to deny them the ability to make changes easily.  If
you believe that then you will never see Lisp as a good thing because
providing the ability to make changes easily is the whole point.  But I am
not interested in arguing about Lisp vs. Java on Java's terms.  Of course
Lisp will lose if you start with the premise that its central feature is
in fact a bug.  But I think that there are people who will look at that
page-long explanation of all you have to do to bind Java objects to
databases and compare that to:

(defclass foo (storable) ...)

(store (make-instance foo))

and start to entertain the idea that maybe there is a point to having all
those irritating silly parentheses after all.

E.
From: Pete Kirkham
Subject: Re: CLOS and databases
Date: 
Message-ID: <405cc723$0$6555$cc9e4d1f@news-text.dial.pipex.com>
Erann Gat wrote:
> Yes, there is a long-standing tension between two fundamentally different
> philosophies about how code should be written.  The first philosophy is
> that you should have two distinct phases, design and coding, and that
> design should be complete before coding begins.  

This is irrelevant to the edit-build-run loop vs the REP loop; you can 
design then code lisp if you choose, you can (with an iterative cycle of 
milliseconds) edit-build-run Java. Faster machines, incremental 
compilers, and hot-swapping classes whilst debugging make iterative 
development with compiled languages the norm. I find that once you are 
dealing with over a hundred lines of code you have to use an editor for 
lisp too, so the difference today is do I drag&drop (load "foo.lisp") 
into the rep loop or hit the recompile-and-run button.

[Java head off:
That said, when I'm doing 'explorative programming' rather than 
'iterative development' ie at the beginning of a problem making a spike 
solution with a most a few hundred lines of code, lisp wins every time. 
But for that problems that size, you don't care about DB persistence.]

> But I think that there are people who will look at that
> page-long explanation of all you have to do to bind Java
 > objects to databases and

(in your argument to those you wish to convince) Summarize the tools 
available for metadata based programming in a typical commercial lisp 
environment, the existing frameworks for DB persistence, and the way 
such frameworks interact with the environment. Is it less than a page long?

 > compare that to:
> 
> (defclass foo (storable) ...)
> 
> (store (make-instance foo))
> 
> and start to entertain the idea that maybe there is a point to having all
> those irritating silly parentheses after all.

==>
   Error: While computing the class precedence list of the class
          named STORABLE.

Are you sure you don't need to have any libraries or frameworks imported 
into your development environment like I explained you do in Java? ;-)

It seems that once per project you will need to tell your lisp 
environment to include the framework you're designing, which is no more 
or less painful with Java environments, and tell each of your storable 
classes which tables to store what slots to. If you only allow the 
facility to store to the table with the name of the class, to store all 
slots, and to fields with the same name as the slots, then your 
persistence mechanism breaks each time you refactor your classes, and 
you break the capability for iterative development. You won't get Java 
people to switch to a mechanism that takes that away from them- it's the 
key thing that Java sells itself on. That is _why_ the Java version is 
more verbose, by including attributes that set the table mapping- so 
that you can do iterative development.

Assuming you have your framework installed and your environment set up 
as previously described, then you have only need add the single 
@hibernate.class tag to the class to enable persistence, and the rest of 
_code_ you have to add to use it is describing the mapping of classes to 
tables and java fields to db fields. So the benefit, by the above 
example, is that with lisp it takes 8 less characters per class- the 
difference between typing 'storable' and ·@hibernate.class[return]'. 
That really isn't a big gain. Maybe a second of developer time for the 
typing, with the same amount of cognative effort per class whatever the 
framework. Clients will spend far more time deciding on the mapping than 
typing the code.

This is not to say that doing transparent persistence using a lisp MOP 
won't take you less time to develop than it took the developers to build 
the Java tools (as you have the metadata accessible directly, and the 
:before and :after built in rather than having to write parsers and byte 
code manipulation routines to add it), nor that there is a theoretical 
cleanness in having it all in the one environment rather than using 
scripting tools, frameworks, postprocessors etc. But IMO this seems a 
case where a framework built on top of lisp can only be shown to be as 
good as, not better than, the existing frameworks available.

Are you selling this to the framework writers or the application 
writers? If the former, then the ease of development for the framework 
is significant. If you are selling lisp on the facilities to extend the 
language then it wins. If you are using those facilities to create a 
framework that has the same functionality as other frameworks in other 
languages, then the judgement is made on the functionality of the 
framework, and it's at best going to be a dead heat.

Using either the hypothetical lisp library or the extant Java tools, the 
application developer has to set up the environment once per project, 
type one word per class to mark it as storable, and specify the 
mappings. The differences in syntax are insignificant, as most the 
effort is deciding the mappings, not typing them.

In a commercial environment where things like DB persistence matter, 
convincing someone to change to something that is only as-good-as the 
current frameworks (that have many thousands of users, so are proven, 
and easier recruitment of people with experience, etc., etc.), you'll 
find it's better the devil you know. If you are selling to framework 
providers, then they will want to create frameworks that integrate with 
the most client developer's toolsets (unless they are intentionally 
targetting a niche market), which again means lisp loses.

I really don't think this is a killer app for lisp.


My first post-student job was reimplementing an application based on a 
persistant object DB from lisp in C++ as it didn't meet performance 
expectations on late 386 based PCs. As it panned out, most of the 
development time ended up creating a scripting language that allowed the 
end users to customize it. That sort of customizability thing is much 
closer to killer lisp than a persistence framework, which costs the app 
developer about the same effort in either lisp or Java to use. The same 
applies to the language manipulation tools and cross compilers I work on 
now- lisp has the better features for these applications.

If you want to write a persistence framework in lisp, do so; just do it 
because you think it will be something worthwhile in and of itself (or 
you need the money and can persuade someone to pay you for it). Doing it 
to impress (or depress) developers who use other languages (often 
because they have to for reasons beyond their control) doesn't seem a 
good thing.


Pete
From: Erann Gat
Subject: Re: CLOS and databases
Date: 
Message-ID: <gNOSPAMat-2003042249150001@192.168.1.51>
In article <························@news-text.dial.pipex.com>, Pete
Kirkham <·················@cafemosaic.co.uk> wrote:

> > (defclass foo (storable) ...)
> > 
> > (store (make-instance foo))
> > 
> > and start to entertain the idea that maybe there is a point to having all
> > those irritating silly parentheses after all.
> 
> ==>
>    Error: While computing the class precedence list of the class
>           named STORABLE.
> 
> Are you sure you don't need to have any libraries or frameworks imported 
> into your development environment like I explained you do in Java? ;-)

Well, of course you'd have to have the code loaded.  Duh!

Where's Erik when we need him?

E.
From: Marc Spitzer
Subject: Re: CLOS and databases
Date: 
Message-ID: <86fzc29ik3.fsf@bogomips.optonline.net>
·········@jpl.nasa.gov (Erann Gat) writes:

>
> Where's Erik when we need him?
>
> E.

Did not you help drive him off when he came back
a few months ago?

marc
From: Erann Gat
Subject: Re: CLOS and databases
Date: 
Message-ID: <gNOSPAMat-2103041132450001@192.168.1.51>
In article <··············@bogomips.optonline.net>, Marc Spitzer
<········@optonline.net> wrote:

> ·········@jpl.nasa.gov (Erann Gat) writes:
> 
> >
> > Where's Erik when we need him?
> >
> > E.
> 
> Did not you help drive him off when he came back
> a few months ago?

How would I know?  I have no particular insight into his motivations, and
he doesn't confide in me.  I note in passing that he announced his
departure in a thread in which I was not participating, so I think it's
possible that the answer to your question could in fact be "no".

Not that any of this matters.

E.
From: Kenny Tilton
Subject: Who Killed Whom? [was Re: CLOS and databases]
Date: 
Message-ID: <BDo7c.2949$1C1.1562006@twister.nyc.rr.com>
> In article <··············@bogomips.optonline.net>, Marc Spitzer
> <········@optonline.net> wrote:
> 
> 
>>·········@jpl.nasa.gov (Erann Gat) writes:
>>
>>
>>>Where's Erik when we need him?
>>>
>>>E.
>>
>>Did not you help drive him off when he came back
>>a few months ago?

No, that was Barry, but only as the proximate cause. The ultimate causes 
were c.l.l. being bad for Erik's health, and Erik being bright enough to 
figure that out. He should try again every year, tho.

Erann did nothing other than be himself, and that is one of his charms. 
I consider him the second constant of the universe, after the speed of 
light in a vacuum.

kt

-- 
  Home? http://tilton-technology.com
Cells? http://www.common-lisp.net/project/cells/
Cello? http://www.common-lisp.net/project/cello/
From: Erann Gat
Subject: Re: Who Killed Whom? [was Re: CLOS and databases]
Date: 
Message-ID: <gNOSPAMat-2203041145010001@k-137-79-50-101.jpl.nasa.gov>
In article <······················@twister.nyc.rr.com>, Kenny Tilton
<·······@nyc.rr.com> wrote:

> > In article <··············@bogomips.optonline.net>, Marc Spitzer
> > <········@optonline.net> wrote:
> > 
> > 
> >>·········@jpl.nasa.gov (Erann Gat) writes:
> >>
> >>
> >>>Where's Erik when we need him?
> >>>
> >>>E.
> >>
> >>Did not you help drive him off when he came back
> >>a few months ago?
> 
> No, that was Barry, but only as the proximate cause. The ultimate causes 
> were c.l.l. being bad for Erik's health, and Erik being bright enough to 
> figure that out. He should try again every year, tho.
> 
> Erann did nothing other than be himself, and that is one of his charms. 
> I consider him the second constant of the universe, after the speed of 
> light in a vacuum.

Erik also did nothing other than to be himself.  Likewise for Marc, Barry,
Pascal, and even you, Kenny.

Not least among the many ironies of the recurring internecine sniping on
c.l.l. is that all the participants are so much alike.

E.
From: Kenny Tilton
Subject: Re: Who Killed Whom? [was Re: CLOS and databases]
Date: 
Message-ID: <hEJ7c.1601$t_4.2143726@twister.nyc.rr.com>
Erann Gat wrote:

> In article <······················@twister.nyc.rr.com>, Kenny Tilton
> <·······@nyc.rr.com> wrote:
>>Erann did nothing other than be himself, and that is one of his charms. 
>>I consider him the second constant of the universe, after the speed of 
>>light in a vacuum.
> 
> 
> Erik also did nothing other than to be himself. 

Wrong, in the sense I meant. Anyone paying attention could see a 
different approach to Usenet, though some things carried over. The 
brusque treatment of a newby was an unfortunate classic, but other 
things were a sea change in tactics. Hell, he even offered me public 
advice here on how I could deal better with you clowns, a moment I rank 
with having John McCarthy use my laptop at ILC 2003 (have I mentioned 
that? recently, I mean) and Paul Graham sending me a (buggy!) tip* on 
soccer defense for my RoboCup team.

kenny the groupie

* "The defensive player simply always stays between the ball and the goal."

-- 
Home? http://tilton-technology.com
Cells? http://www.common-lisp.net/project/cells/
Cello? http://www.common-lisp.net/project/cello/
From: Sashank Varma
Subject: Re: Who Killed Whom? [was Re: CLOS and databases]
Date: 
Message-ID: <none-BD4548.17173122032004@news.vanderbilt.edu>
In article <······················@twister.nyc.rr.com>,
 Kenny Tilton <·······@nyc.rr.com> wrote:

> Hell, he even offered me public 
> advice here on how I could deal better with you clowns, a moment I rank 
> with having John McCarthy use my laptop at ILC 2003 (have I mentioned 
> that? recently, I mean) and Paul Graham sending me a (buggy!) tip* on 
> soccer defense for my RoboCup team.
> 
> kenny the groupie
> 
> * "The defensive player simply always stays between the ball and the goal."

kenny the groupie, if these are the kinds of tips that
apply to RoboCup, there are more to be found on the
basketball courts and soccer fields where 4-8 year old
children play.  I coach my young daughters and their
classmates, and it's amazing how this forces you to
articulate every rule and heuristics which you, as a
skilled player, long ago internalized -- automatized and
forgot.  Less than three weeks ago I was admonishing
my kindergarten team to "stay between your girl and
the goal" while playing defense.  Well, not admonishing,
but yelling at the top of my lungs from the sideline.
From: Ng Pheng Siong
Subject: Re: Who Killed Whom? [was Re: CLOS and databases]
Date: 
Message-ID: <c3ntl6$4vh$1@reader01.singnet.com.sg>
According to Sashank Varma  <····@vanderbilt.edu>:
> In article <······················@twister.nyc.rr.com>,
>  Kenny Tilton <·······@nyc.rr.com> wrote:
> > * "The defensive player simply always stays between the ball and the goal."
> 
> Less than three weeks ago I was admonishing
> my kindergarten team to "stay between your girl and
> the goal" while playing defense.  Well, not admonishing,
> but yelling at the top of my lungs from the sideline.

There is no offside rule in kindergarten and computer football?


-- 
Ng Pheng Siong <····@netmemetic.com> 

http://firewall.rulemaker.net -+- Firewall Change Management & Version Control
http://sandbox.rulemaker.net/ngps -+- Open Source Python Crypto & SSL
From: Kenny Tilton
Subject: Re: Who Killed Whom? [was Re: CLOS and databases]
Date: 
Message-ID: <StM7c.1610$t_4.2237098@twister.nyc.rr.com>
Ng Pheng Siong wrote:
> According to Sashank Varma  <····@vanderbilt.edu>:
> 
>>In article <······················@twister.nyc.rr.com>,
>> Kenny Tilton <·······@nyc.rr.com> wrote:
>>
>>>* "The defensive player simply always stays between the ball and the goal."
>>
>>Less than three weeks ago I was admonishing
>>my kindergarten team to "stay between your girl and
>>the goal" while playing defense.  Well, not admonishing,
>>but yelling at the top of my lungs from the sideline.

Ah, fond memories of going "Bobby Knight"* on Rita Amicucci, actually 
kicking a chair when five seconds after being admonished to stick like 
glue to her opponent I located her some fifty feet away from her 
opponent who was scoring a lay-up**.

I swear to god the opposing coach came over to try to calm me down. :)


> There is no offside rule in kindergarten and computer football?

Or professional football. It is always a judgment call, so if Rinaldo 
were offsides but over at the sideline, back to the goal, and crying for 
his Mommy, the ref would not make the call. Or so I hear.

kt

* American basketball coach who once threw a chair across a basketball 
court, choked a student for perceived rudeness, and generally was a 
poster boy for high blood pressure.

** Easy two points in basketball.



-- 
Home? http://tilton-technology.com
Cells? http://www.common-lisp.net/project/cells/
Cello? http://www.common-lisp.net/project/cello/
Why Lisp? http://alu.cliki.net/RtL%20Highlight%20Film
Your Project Here! http://alu.cliki.net/Industry%20Application
From: Barry Wilkes
Subject: Re: Who Killed Whom?
Date: 
Message-ID: <fzc0aukn.fsf@acm.org>
Kenny Tilton <·······@nyc.rr.com> writes:
<snip>
> ...
> laptop at ILC 2003 (have I mentioned that? recently, I mean) and Paul Graham
> sending me a (buggy!) tip* on soccer defense for my RoboCup team.
>
> kenny the groupie
>
> * "The defensive player simply always stays between the ball and the goal."
>
Pah!  Americans and football!  Lookup the Offside rule.  Study 'The Arsenal
Back-Four' (until fairly recently anyway).

Tony Adams should clearly spend his retirement helping Kenny.

;)

Barry.
From: Kenny Tilton
Subject: Re: Who Killed Whom?
Date: 
Message-ID: <6NT7c.4057$1C1.2241613@twister.nyc.rr.com>
Barry Wilkes wrote:

> Kenny Tilton <·······@nyc.rr.com> writes:
> <snip>
> 
>>...
>>laptop at ILC 2003 (have I mentioned that? recently, I mean) and Paul Graham
>>sending me a (buggy!) tip* on soccer defense for my RoboCup team.
>>
>>kenny the groupie
>>
>>* "The defensive player simply always stays between the ball and the goal."
>>
> 
> Pah!  Americans and football!  Lookup the Offside rule.  Study 'The Arsenal
> Back-Four' (until fairly recently anyway).

<heh-heh> You guys all missed the bug! And it has nothing to do with 
offsides rules. I'll give you one more try.

kt

-- 
Home? http://tilton-technology.com
Cells? http://www.common-lisp.net/project/cells/
Cello? http://www.common-lisp.net/project/cello/
From: Tayssir John Gabbour
Subject: Re: Who Killed Whom?
Date: 
Message-ID: <866764be.0403231131.7f23d405@posting.google.com>
Kenny Tilton <·······@nyc.rr.com> wrote in message news:<······················@twister.nyc.rr.com>...
> <heh-heh> You guys all missed the bug! And it has nothing to do with 
> offsides rules. I'll give you one more try.

Hmm, the the defensive player should stay in between IF POSSIBLE?

A defensive player should occasionally go on offense, such as near the
end when losing?

I'm assuming soccer is anything like hockey, which I do like.
From: Kenny Tilton
Subject: Re: Who Killed Whom?
Date: 
Message-ID: <cv18c.5019$1C1.2440675@twister.nyc.rr.com>
Tayssir John Gabbour wrote:

> Hmm, the the defensive player should stay in between IF POSSIBLE?
> 
> A defensive player should occasionally go on offense, such as near the
> end when losing?

No, you are looking for a great, honking bug, not at the level of 
unsound soccer strategy ("the best defense is a good offense"), but 
rather at the level of ("oh, jeez, hang on...") if this advice were to 
be followed:

  "when the other team has the ball, your players should simply stay 
between the ball and their own goal"

btw, i am also not talking about that formulation leaving unspecified 
how to determine purely by sight that "the other team has the ball".

kt

-- 
Home? http://tilton-technology.com
Cells? http://www.common-lisp.net/project/cells/
Cello? http://www.common-lisp.net/project/cello/
Why Lisp? http://alu.cliki.net/RtL%20Highlight%20Film
Your Project Here! http://alu.cliki.net/Industry%20Application
From: Tayssir John Gabbour
Subject: Re: Who Killed Whom?
Date: 
Message-ID: <866764be.0403231848.11bbcb77@posting.google.com>
Kenny Tilton <·······@nyc.rr.com> wrote in message news:<······················@twister.nyc.rr.com>...
> No, you are looking for a great, honking bug, not at the level of 
> unsound soccer strategy ("the best defense is a good offense"), but 
> rather at the level of ("oh, jeez, hang on...") if this advice were to 
> be followed:

Hmm, I guess that rules out guarding BOTS instead of just the ball? 
Because you want to obstruct potential lines to goal (and passing
lanes) instead of the current line to goal.
From: Gareth McCaughan
Subject: Re: Who Killed Whom?
Date: 
Message-ID: <877jxb5ibb.fsf@g.mccaughan.ntlworld.com>
Kenny Tilton <·······@nyc.rr.com> writes:

> Tayssir John Gabbour wrote:
> 
> > Hmm, the the defensive player should stay in between IF POSSIBLE?
> > A defensive player should occasionally go on offense, such as near
> > the
> > end when losing?
> 
> No, you are looking for a great, honking bug, not at the level of
> unsound soccer strategy ("the best defense is a good offense"), but
> rather at the level of ("oh, jeez, hang on...") if this advice were to
> be followed:
> 
>   "when the other team has the ball, your players should simply stay
> between the ball and their own goal"

When the ball is at all near the goal, the location of "the goal"
is pretty poorly defined. Naive implementation of this rule could
lead to the edges of the goal being undefended.

The goal extends into the pitch. If the ball (with an attacking
player) is "past the goalmouth" then there is no point in having
defending players between the ball and the goal, since it can't
get in directly.

If all your players are independently trying to get between the
ball and the goal then they will collide with each other and end up
in a heap.

I don't believe any of these is what you're looking for :-).

-- 
Gareth McCaughan
.sig under construc
From: Kenny Tilton
Subject: Re: Who Killed Whom?
Date: 
Message-ID: <ab68c.5047$1C1.2551483@twister.nyc.rr.com>
Gareth McCaughan wrote:

> Kenny Tilton <·······@nyc.rr.com> writes:
> 
> 
>>Tayssir John Gabbour wrote:
>>
>>
>>>Hmm, the the defensive player should stay in between IF POSSIBLE?
>>>A defensive player should occasionally go on offense, such as near
>>>the
>>>end when losing?
>>
>>No, you are looking for a great, honking bug, not at the level of
>>unsound soccer strategy ("the best defense is a good offense"), but
>>rather at the level of ("oh, jeez, hang on...") if this advice were to
>>be followed:
>>
>>  "when the other team has the ball, your players should simply stay
>>between the ball and their own goal"
> 
> 
> When the ball is at all near the goal, the location of "the goal"
> is pretty poorly defined.

I think being on the bisector of the angle from the ball and between the 
goalposts is optimal. that's where I had the goalie go, anyway.

  Naive implementation of this rule could
> lead to the edges of the goal being undefended.
> 
> The goal extends into the pitch. If the ball (with an attacking
> player) is "past the goalmouth" then there is no point in having
> defending players between the ball and the goal, since it can't
> get in directly.
> 
> If all your players are independently trying to get between the
> ball and the goal then they will collide with each other and end up
> in a heap.

Possibly, but they will certainly end up in a line from the ball to the 
goal.

> 
> I don't believe any of these is what you're looking for :-).
> 

I am giving partial credit for the heap of players answer.

:)

kt

-- 
Home? http://tilton-technology.com
Cells? http://www.common-lisp.net/project/cells/
Cello? http://www.common-lisp.net/project/cello/
Why Lisp? http://alu.cliki.net/RtL%20Highlight%20Film
Your Project Here! http://alu.cliki.net/Industry%20Application
From: Jens Axel Søgaard
Subject: Re: Who Killed Whom?
Date: 
Message-ID: <40604cbb$0$289$edfadb0f@dread11.news.tele.dk>
Kenny Tilton wrote:

>>> * "The defensive player simply always stays between the ball and the 
>>> goal."

> <heh-heh> You guys all missed the bug! And it has nothing to do with 
> offsides rules. I'll give you one more try.

I'll bite.

  - the goal is the defenders goal

  - there is (hopefully) more than one defensive player

  - if the ball is free, the defender should run towards
    the ball to gain control of it

  - what happens if the defenders goalie has the ball?

  - the player is slower than the ball leading to:

      Attacker1 ---ball---> Attacker2


             ---Defender--->

         X



                  goal

    While the ball move from attacker 1 to attacker 2,
    attacker 1 runs towards and the goal and is free
    to receive the ball from attacker 2 at the spot
    marked X. There is now a possibility for a free shot.

-- 
Jens Axel S�gaard
From: Kenny Tilton
Subject: All your fullbacks are belong to us [was Re: Who Killed Whom?]
Date: 
Message-ID: <h%%7c.5012$1C1.2416295@twister.nyc.rr.com>
Jens Axel S�gaard wrote:

> Kenny Tilton wrote:
> 
>>>> * "The defensive player simply always stays between the ball and the 
>>>> goal."
> 
> 
>> <heh-heh> You guys all missed the bug! And it has nothing to do with 
>> offsides rules. I'll give you one more try.
> 
> 
> I'll bite.

fyi, i could not make out if the following was a scenario constituting 
one guess or separate guesses. They look separate.

> 
>  - the goal is the defenders goal

Did you mean "attacker's"? No, it is not a trick question. "The other 
team has the ball, my players should stay between the ball and the goal 
they defend" was his advice.

> 
>  - there is (hopefully) more than one defensive player

Correct solution ingredient #1!

> 
>  - if the ball is free, the defender should run towards
>    the ball to gain control of it

Maybe if they are a few yards away, but the shortest distance to a line 
is a perpendicular to that line, so if there are big distances involved 
they get between the ball and the goal faster by running to the line, 
not the ball.

Anyone starting to see why RoboCup was so much fun?

> 
>  - what happens if the defenders goalie has the ball?

Then Paul's rule flips and applies to the other team. And again, this 
was a solid bug, not a trick one.* I understood Paul meant that the 
attackers had crossed midfield.

This is not to say I was not guilty of bugs at this so-called trick 
level, just that in this case the bug I am after does not rely on 
forgetting that a goalie is a player or something of that ilk.


> 
>  - the player is slower than the ball leading to:
> 
>      Attacker1 ---ball---> Attacker2
> 
> 
>             ---Defender--->
> 
>         X

Correct solution ingredient #2! Tho this in its own right is indeed a 
problem because the soccer server tracks player exertion and applies a 
fatigue factor before executing player commands.

Mix, stir, bake and....?

kt

-- 
Home? http://tilton-technology.com
Cells? http://www.common-lisp.net/project/cells/
Cello? http://www.common-lisp.net/project/cello/
Why Lisp? http://alu.cliki.net/RtL%20Highlight%20Film
Your Project Here! http://alu.cliki.net/Industry%20Application
From: Marco Antoniotti
Subject: Re: All your fullbacks are belong to us [was Re: Who Killed Whom?]
Date: 
Message-ID: <HK38c.123$IJ5.110187@typhoon.nyu.edu>
It is well known that you need one attacker (usually no. 9) one goalie 
and 9 defenders in soccer.  I do not understand all the complications 
you are putting up.

Cheers

Marco

PS.  Of course it helps if the attacker is named Rossi or Schillaci or 
Vieri or Totti and he is in a state of grace the day of the match :)





Kenny Tilton wrote:
> 
> 
> Jens Axel S�gaard wrote:
> 
>> Kenny Tilton wrote:
>>
>>>>> * "The defensive player simply always stays between the ball and 
>>>>> the goal."
>>
>>
>>
>>> <heh-heh> You guys all missed the bug! And it has nothing to do with 
>>> offsides rules. I'll give you one more try.
>>
>>
>>
>> I'll bite.
> 
> 
> fyi, i could not make out if the following was a scenario constituting 
> one guess or separate guesses. They look separate.
> 
>>
>>  - the goal is the defenders goal
> 
> 
> Did you mean "attacker's"? No, it is not a trick question. "The other 
> team has the ball, my players should stay between the ball and the goal 
> they defend" was his advice.
> 
>>
>>  - there is (hopefully) more than one defensive player
> 
> 
> Correct solution ingredient #1!
> 
>>
>>  - if the ball is free, the defender should run towards
>>    the ball to gain control of it
> 
> 
> Maybe if they are a few yards away, but the shortest distance to a line 
> is a perpendicular to that line, so if there are big distances involved 
> they get between the ball and the goal faster by running to the line, 
> not the ball.
> 
> Anyone starting to see why RoboCup was so much fun?
> 
>>
>>  - what happens if the defenders goalie has the ball?
> 
> 
> Then Paul's rule flips and applies to the other team. And again, this 
> was a solid bug, not a trick one.* I understood Paul meant that the 
> attackers had crossed midfield.
> 
> This is not to say I was not guilty of bugs at this so-called trick 
> level, just that in this case the bug I am after does not rely on 
> forgetting that a goalie is a player or something of that ilk.
> 
> 
>>
>>  - the player is slower than the ball leading to:
>>
>>      Attacker1 ---ball---> Attacker2
>>
>>
>>             ---Defender--->
>>
>>         X
> 
> 
> Correct solution ingredient #2! Tho this in its own right is indeed a 
> problem because the soccer server tracks player exertion and applies a 
> fatigue factor before executing player commands.
> 
> Mix, stir, bake and....?
> 
> kt
> 
From: Coby Beck
Subject: Re: All your fullbacks are belong to us [was Re: Who Killed Whom?]
Date: 
Message-ID: <c3qd6b$2hfi$1@otis.netspace.net.au>
> > Kenny Tilton wrote:
> >
> >>>> * "The defensive player simply always stays between the ball and the
> >>>> goal."
> >
> >
> >> <heh-heh> You guys all missed the bug! And it has nothing to do with
> >> offsides rules. I'll give you one more try.
> >
> Mix, stir, bake and....?
>
> kt

...and you have your typical elementary school soccer game!  A great big
honking crowd of players *all together* running around in a group after the
ball instead of playing their opponents and their positions.


-- 
Coby Beck
(remove #\Space "coby 101 @ big pond . com")
From: Kenny Tilton
Subject: Re: All your fullbacks are belong to us [was Re: Who Killed Whom?]
Date: 
Message-ID: <W268c.5045$1C1.2547035@twister.nyc.rr.com>
Coby Beck wrote:
>>>Kenny Tilton wrote:
>>>
>>>
>>>>>>* "The defensive player simply always stays between the ball and the
>>>>>>goal."
>>>
>>>
>>>><heh-heh> You guys all missed the bug! And it has nothing to do with
>>>>offsides rules. I'll give you one more try.
>>>
>>Mix, stir, bake and....?
>>
>>kt
> 
> 
> ...and you have your typical elementary school soccer game!  A great big
> honking crowd of players *all together* running around in a group after the
> ball instead of playing their opponents and their positions.

Pretty close. I wrote back, "Doesn't that mean all my players end up in 
a /line/ between the ball and the goal?". So he sent along a patch. I 
think it was to stay between the player you are marking and the goal.

And, yes, TeamKenny played a lot of kindergarten soccer, and when I 
tried to teach them zone play, oh my....

:)

kt

-- 
Home? http://tilton-technology.com
Cells? http://www.common-lisp.net/project/cells/
Cello? http://www.common-lisp.net/project/cello/
Why Lisp? http://alu.cliki.net/RtL%20Highlight%20Film
Your Project Here! http://alu.cliki.net/Industry%20Application
From: David Steuber
Subject: Re: Who Killed Whom? [was Re: CLOS and databases]
Date: 
Message-ID: <m2ekrkmmnl.fsf@david-steuber.com>
·········@jpl.nasa.gov (Erann Gat) writes:

> Not least among the many ironies of the recurring internecine sniping on
> c.l.l. is that all the participants are so much alike.

Well, I'm no rocket scientist.

-- 
It would not be too unfair to any language to refer to Java as a
stripped down Lisp or Smalltalk with a C syntax.
--- Ken Anderson
    http://openmap.bbn.com/~kanderso/performance/java/index.html
From: Pete Kirkham
Subject: Re: CLOS and databases
Date: 
Message-ID: <405de619$0$6551$cc9e4d1f@news-text.dial.pipex.com>
Erann Gat wrote:

> In article <························@news-text.dial.pipex.com>, Pete
> Kirkham <·················@cafemosaic.co.uk> wrote:
>>Are you sure you don't need to have any libraries or frameworks imported 
>>into your development environment like I explained you do in Java? ;-)
> 
> Well, of course you'd have to have the code loaded.  Duh!

So, having established that you need to do at least as much as what you 
have to do in Java (set up environment, define mappings if not using 
default), where is the big advantage?

A system that only allows mapping to a fresh DB isn't going to impress 
anyone using Java, when one of the principle areas of application of 
Java is putting front ends onto legacy business systems.

 > Where's Erik when we need him?

Could you explain the reference?


Pete
From: Erann Gat
Subject: Re: CLOS and databases
Date: 
Message-ID: <gNOSPAMat-2103041109370001@192.168.1.51>
In article <························@news-text.dial.pipex.com>, Pete
Kirkham <·················@cafemosaic.co.uk> wrote:

> Erann Gat wrote:
> 
> > In article <························@news-text.dial.pipex.com>, Pete
> > Kirkham <·················@cafemosaic.co.uk> wrote:
> >>Are you sure you don't need to have any libraries or frameworks imported 
> >>into your development environment like I explained you do in Java? ;-)
> > 
> > Well, of course you'd have to have the code loaded.  Duh!
> 
> So, having established that you need to do at least as much as what you 
> have to do in Java (set up environment, define mappings if not using 
> default), where is the big advantage?

The advantage is that to do all that that took you a whole page of text to
describe is done in Lisp by:

(require 'gat-object-store)

>  > Where's Erik when we need him?
> 
> Could you explain the reference?

No.  But I'm sure someone else will.

E.
From: Pete Kirkham
Subject: Re: CLOS and databases
Date: 
Message-ID: <405e0e2d$0$3302$cc9e4d1f@news-text.dial.pipex.com>
Erann Gat wrote:
> The advantage is that to do all that that took you a whole page of text to
> describe is done in Lisp by:
> 
> (require 'gat-object-store)

To a Java audience, I could have said is 'all that you do is install 
XDoclet and hibernate, cut&paste the Ant tasks to call them, then add an 
@hibernate.class doctag for each class you wish to map to the DB'. As 
this is a lisp news group, I felt more detail appropriate.

My understanding of require is that there is a precondition that you 
already have installed the required package in a place where your 
environment can access it. So even in lisp there is still more to do 
than you seem willing to admit.

It can take less that 15 minutes to set up XDoclet and Hibernate per 
project. Compare that to the loss of functionality you propose by only 
supporting one default mapping to a database, and it seems you will lose 
your argument. Even if it takes your best developer a week to set up a 
library, it is worth it in the really real world if the project gains 
more functionality than that developer can create in that time.

If your only purpose is to impress a Java developer audience, why are 
you not addressing the points I made?  'Duh' as a response to being 
shown a counter example to your position isn't going to knock anyone's 
socks off.

Someone posted a link to one of Eric's posts. Taking that as a lead, are 
you implying that you can show that a one-man project that uses CLOS/MOP 
can be calmly and rationally shown to better than the existing Java 
solutions?

Taking your particular case, independent of the other arguments about 
language elegance (lisp wins hands down), edit-compile-run vs REP (true 
when you worked with punch cards, but had disappeared by the mid'90s 
with incremental compile and better debuggers), and a belief that Java 
is fixed to the waterfall development model (simply untrue), some things 
you can compare on are functionality, cost, integration, reliability, 
scalability, architecture.

Functionality:
The solution you are proposing has massively reduced functionality with 
respect to the usecases that typical Java systems require.

A typical Java application that requires DB persistence will be a web 
front end to an existing database. You can't use your solution for that.

Cost:
Once placed in a location accessible to the environment, the solution 
you are proposing can be installed easily with single command, instead 
of taking maybe half an hour for the Java version.

The cost per class is about the same- typing 'storable' vs. 
·@hibernate.class'

Integration:
The solution you are proposing transparently integrates with the lisp 
environment. It does not integrate with business infrastructures, such 
as existing databases.
The existing Java solutions (well, hibernate anyway) require an explicit 
update command. They can be configured to operate with existing business 
infrastructures.

Reliability:
There's always FUD about anything that is different. Hard to measure.

Scalability:
Hitting a DB for every slot access kills performance. Once you have 
start caching your transactions, it may well be that the naive approach 
fails. If you restrict yourself to only the information available 
through the MOP, without providing any mechanism for the user to 
customize the mapping and the caching, then it is very unlikely your 
scheme will scale. Once you realise that you don't want overhead on 
every access, maybe transparency isn't that important.

Architecture:
Java applications separate persistence mechanisms into a different layer 
to the type hierarchy which encapsulates the business logic.

If you are arguing with people familiar with layered architectures and 
unfamiliar with the CLOS style of OO, then you need to explain why you 
are polluting the type space with orthogonal concerns. There is no such 
thing as a mixin in Java; this was intentional, not an omission.


I've already replied with application areas that IMO lisp does 'win' 
over less dynamic environments, but yet another lisp programmer showing 
how to make cool toys isn't going to win any serious software engineer 
over.

Lisp can be better than Java, but to convince people you have to address 
their concerns, not your own.  No-one programs in Java if they believe 
language-level elegance is more important that practicality. Concorde 
was more elegant and capable on its own terms than any other airliner, 
but it couldn't survive in the market.


Pete
From: Erann Gat
Subject: Re: CLOS and databases
Date: 
Message-ID: <gNOSPAMat-2103041640380001@192.168.1.51>
In article <························@news-text.dial.pipex.com>, Pete
Kirkham <·················@cafemosaic.co.uk> wrote:

> If your only purpose is to impress a Java developer audience

But it isn't.  That isn't even my main purpose, let alone my only purpose.

> why are you not addressing the points I made?

Because the points you made are all non-sequiturs, as they are all based
on incorrect assumptions.  (Well, they weren't all non-sequiturs.  At
least one of them, that you'd get an error if you tried to use the
software without loading it, was just plain stupid.  I pretty much tuned
out at that point.)

My primary purpose is to build a tool for a particular need that I have
for which I have not found anything adequate off the shelf.  I have found
in building this tool that it is turning out to be easier than I expected
(and I wasn't expecting it to be particularly hard) and that has caused me
to up-scope a little to include the possibility of turning it into a
little showcase piece.  But I don't expect anyone to be impressed by what
it does, because it isn't going to do anything that you can't do in Java
(or anything else for that matter) by simply doing X, Y and Z.  But the
point, of course, will be that you don't have to do X, Y and Z.  Some
people will get it, and some people won't, and I have absolutely no
interest in arguing with the latter (especially not here on c.l.l.).  I
have finally learned what an old mentor of mine meant when he once told
me, "Never try to teach a pig to sing.  It wastes your time and annoys the
pig."

E.
From: a
Subject: Re: CLOS and databases
Date: 
Message-ID: <MLv7c.73069$vn.219100@sea-read.news.verio.net>
"Erann Gat" <·········@jpl.nasa.gov> wrote in message
·······························@192.168.1.51...
> In article <························@news-text.dial.pipex.com>, Pete
> Kirkham <·················@cafemosaic.co.uk> wrote:
>
> > If your only purpose is to impress a Java developer audience
>
> But it isn't.  That isn't even my main purpose, let alone my only purpose.
>
...
> But I don't expect anyone to be impressed by what
> it does, because it isn't going to do anything that you can't do in Java
> (or anything else for that matter) by simply doing X, Y and Z.
...
 "Never try to teach a pig to sing.  It wastes your time and annoys the
> pig."
>
> E.

Come off it. In your post that started this thread you said:

"My goal here is not only to make something functional, but also to
highlight the power of CLOS with something that will really knock the
socks off the Java people, so I really want to do this the Right Way."

People tried to tell you what you had to do to knock the socks off the Java
people because that's what you said you wanted to do. You found it was hard,
now you don't want to do it, and because of that we are pigs?

Where is Mike (Godwin) when you need him?
From: David Steuber
Subject: Re: CLOS and databases
Date: 
Message-ID: <m2zna9nu8x.fsf@david-steuber.com>
"a" <···@def.gh> writes:

> Come off it. In your post that started this thread you said:
> 
> "My goal here is not only to make something functional, but also to
> highlight the power of CLOS with something that will really knock the
> socks off the Java people, so I really want to do this the Right Way."

Yeah, he did say that.  But he did not post a complete product spec.
Who doesn't leave out information from time to time in usenet posts?

> People tried to tell you what you had to do to knock the socks off the Java
> people because that's what you said you wanted to do. You found it was hard,
> now you don't want to do it, and because of that we are pigs?

I don't think there is a reason to be offended here.  I'm sure he
ment that Java people are pigs metaphorically.  I doubt he expects
any Java people to be made into bacon.

> Where is Mike (Godwin) when you need him?

I think he made some reference to Hitler and then disappeared.

-- 
Those who do not remember the history of Lisp are doomed to repeat it,
badly.

> (dwim x)
NIL
From: Erann Gat
Subject: Re: CLOS and databases
Date: 
Message-ID: <gNOSPAMat-2203040915440001@192.168.1.52>
In article <·····················@sea-read.news.verio.net>, "a"
<···@def.gh> wrote:

> "Erann Gat" <·········@jpl.nasa.gov> wrote in message
> ·······························@192.168.1.51...
> > In article <························@news-text.dial.pipex.com>, Pete
> > Kirkham <·················@cafemosaic.co.uk> wrote:
> >
> > > If your only purpose is to impress a Java developer audience
> >
> > But it isn't.  That isn't even my main purpose, let alone my only purpose.
> >
> ...
> > But I don't expect anyone to be impressed by what
> > it does, because it isn't going to do anything that you can't do in Java
> > (or anything else for that matter) by simply doing X, Y and Z.
> ...
>  "Never try to teach a pig to sing.  It wastes your time and annoys the
> > pig."
> >
> > E.
> 
> Come off it. In your post that started this thread you said:
> 
> "My goal here is not only to make something functional, but also to
> highlight the power of CLOS with something that will really knock the
> socks off the Java people, so I really want to do this the Right Way."
> 
> People tried to tell you what you had to do to knock the socks off the Java
> people because that's what you said you wanted to do. You found it was hard,
> now you don't want to do it, and because of that we are pigs?

Are you not familiar with the concept of metaphor?

Here's another piece of advice I'm going to follow now: never argue with
an anonymous troll.  Goodbye, "a".

E.
From: Pete Kirkham
Subject: Re: CLOS and databases
Date: 
Message-ID: <405f3eaa$0$6542$cc9e4d1f@news-text.dial.pipex.com>
Erann Gat wrote:
> But it isn't.  That isn't even my main purpose, let alone my only purpose.
It was the purpose you stated for showing it to Java developers.

> Because the points you made are all non-sequiturs, as they are all based
> on incorrect assumptions.  (Well, they weren't all non-sequiturs.  At
> least one of them, that you'd get an error if you tried to use the
> software without loading it, was just plain stupid.  I pretty much tuned
> out at that point.)
The point was that you have to do more than you say you were letting on 
to use your system. You 'tuned it out' by making it the only point you 
responded to.

I don't see that suggesting that people will not be impressed by tools 
that do not solve _their_ problems an non-sequitur.

> I have finally learned what an old mentor of mine meant when he once told
> me, "Never try to teach a pig to sing.  It wastes your time and annoys the
> pig."

Then I will take your advice and stop trying to teach you what my 
experience is of the points you need to address when arguing for using 
lisp in a Java shop. Instead, I suspect that when you showcase your 
framework you will find that the audience remains unimpressed, as when 
they raise the same points about business integration, functionality, 
cost benefit, support for legacy systems and so on, you refuse to answer 
them, and call them pigs.

Assuming your email indicates your place of work (mine is my 'home' 
one), please don't do your showcasing at Nasa, as I work writing 
aerospace system engineering r&d tools, sometimes on joint projects. I 
would prefer not to have my implementation language preferences 
restricted by bad experiences with arrogant twits who also use lisp. 
It's a hard enough sell as it is, even when you do understand the 
business needs that drive people to use Java.


Pete
From: Erann Gat
Subject: Re: CLOS and databases
Date: 
Message-ID: <gNOSPAMat-2203041219140001@k-137-79-50-101.jpl.nasa.gov>
In article <························@news-text.dial.pipex.com>, Pete
Kirkham <·················@cafemosaic.co.uk> wrote:

> The point was that you have to do more than you say you were letting on 
> to use your system.

That you have to load software in order to use it is universally
understood.  To point out that a program won't work if you haven't loaded
it not constructive, it's trolling.

> You 'tuned it out' by making it the only point you responded to.

Life is short.

> I don't see that suggesting that people will not be impressed by tools 
> that do not solve _their_ problems an non-sequitur.

It's a non-sequitur because it's also self-evident.  I already know that
some people will not be impressed by what I'm doing.  That does not mean
that their views have any merit, it just means that they are not part of
my intended audience.  Like I said, some people will get it, and some
people won't, and life is too short to worry about the latter.  (And even
if the set of people who get it turns out to be empty then I'll still have
built a tool that meets *my* needs, which is my main goal here after all.)

> Assuming your email indicates your place of work (mine is my 'home' 
> one), please don't do your showcasing at Nasa, as I work writing 
> aerospace system engineering r&d tools, sometimes on joint projects. I 
> would prefer not to have my implementation language preferences 
> restricted by bad experiences with arrogant twits who also use lisp. 
> It's a hard enough sell as it is, even when you do understand the 
> business needs that drive people to use Java.

You mean, as opposed to bad experiences with people who call people they
don't know "arrogant twits"?

BTW, son, you might want to do a little homework before you lecture me
about selling Lisp to NASA.

E.
From: Pete Kirkham
Subject: Re: CLOS and databases
Date: 
Message-ID: <4060b437$0$6541$cc9e4d1f@news-text.dial.pipex.com>
> BTW, son, you might want to do a little homework before you lecture me
> about selling Lisp to NASA.
Ok, I went and googled your CV.

I'd got the impression from your first post that you didn't have much 
lisp experience, and you were in the 'kid with a new toy' phase and 
going to show it off to some colleagues who were using the current state 
of Java tools to talk to databases. I'm sorry I'd got the wrong 
impression, and was talking at the wrong level, and in the wrong way.

I don't have a CV on-line, but I spent nearly a decade as a researcher 
on kms tool support for aerospace applications at the University of 
York, UK, and for the last few years in the Research&Tech dept. of BAE 
Air Systems. Mix of technologies, lisp, C++, Java, ADA; some code 
analysis, formal verification, and code generation of flight software 
from models.

An area I'm currently working is taking systems engineering models- 
ISO10303/AP233, together with various simulation languages, and 
generating qualitative models for system health monitoring from them. I 
know of no current use of lisp in NASA for this- everything seems to be 
UML and XML, with OWL leanings; the only data-driven lisp project I was 
aware of in the qualitative modelling field (Livingstone) has been 
transitioned to C++.

Too many of the systems and tools I've seen are closed worlds to data- 
the monitoring systems are hand crafted to implicitly capture one 
system's model, not derived from the information already available in 
the organisation. At best, there's a point and click GUI, at worst it's 
all hard coded. Deriving the model, and verifying it, over and over 
again for each tool or monitoring system is prohibitively expensive for 
complex systems or variable configurations, so getting things to talk to 
the organisation is the key selling point.

In the business Java&XML world, a similar driver exists with talking 
with existing databases and applications in the organisation. It is what 
most people use Java for, so for in most IDEs you can set it up in five 
minutes using a wizard, then forget about it.

So I thought I was discussing with a naive lisper who don't 'get' that 
the really big thing in the Java world is being able to talk to data 
sources you don't control, and was going to end up looking like a twit; 
and was playing 'gosling's advocate' to that position. Hopefully we'll 
understand each other better in future.


Pete
From: Erann Gat
Subject: Re: CLOS and databases
Date: 
Message-ID: <gNOSPAMat-2303041446130001@k-137-79-50-101.jpl.nasa.gov>
In article <························@news-text.dial.pipex.com>, Pete
Kirkham <·················@cafemosaic.co.uk> wrote:

> > BTW, son, you might want to do a little homework before you lecture me
> > about selling Lisp to NASA.
> Ok, I went and googled your CV.

Actually, the relevant item for the matter at hand isn't on my CV.


> I'm sorry I'd got the wrong 
> impression, and was talking at the wrong level, and in the wrong way.

Yes, and now you're apologising for the wrong thing.  Rudeness is rudeness
irrespective of what happens to be on the CV of the person you're being
rude to.

Nonetheless, I'll accept the apology in the spirit in which (I assume) it
was offered.  I'm sorry I called you "son".


> So I thought I was discussing with a naive lisper who don't 'get' that 
> the really big thing in the Java world is being able to talk to data 
> sources you don't control

Lisp is actually *vastly* better than Java when it comes to talking to
data sources you don't control.  But that's not what I happen to be
working on right now.  (To say nothing of the fact that I do not accept
your authority to speak on behalf of the entire Java user community.)

> and was going to end up looking like a twit;

Heh, I appreciate your concern.  God knows there have been times when such
concerns have been warranted.  But in this particular case you might want
to take a look in the mirror.

> and was playing 'gosling's advocate' to that position. Hopefully we'll 
> understand each other better in future.

I'm pretty sure I understood you well enough.  You're saying something
along the lines of "You can only impress Java programmers by doing X"
(where X seems to be something like "talking to data sources you don't
control").  The details don't matter because it is easy to see that you
are (almost certainly) wrong simply by the form of the claim.  Java
programmers are too diverse (and research into such things is too sparse)
for such a claim to be plausible.  It is therefore IMO not worthy of
serious consideration.  Also, as I've now said many times, impressing
someone would be a nice bonus, but it's not the primary goal.

E.
From: Kenny Tilton
Subject: Java Is A Dynamic Language? [was Re: CLOS and databases]
Date: 
Message-ID: <S1p7c.2951$1C1.1571494@twister.nyc.rr.com>
Pete Kirkham wrote:

> Taking your particular case, independent of the other arguments about 
> language elegance (lisp wins hands down), edit-compile-run vs REP (true 
> when you worked with punch cards, but had disappeared by the mid'90s 
> with incremental compile and better debuggers)...

Well, let's not get carried away. The mid-90's is exactly when I went on 
my Dynamic-Or-Bust! search and by luck rolled to stop in a crater 
containing Lisp.

Symantec C++ had abandoned the incremental linkage of Think C, and I was 
looking at 30 seconds between runs, incremental compile notwithstanding. 
Unacceptable. Especially since I have never met a line of (my own) code 
I like, so I am always refactoring. (And in C that meant trouble if I 
wanted to change a header in a precompiled header.) I would have to 
propagate everything everywhere every time before ever seeing the 
outcome. The existence of refactoring aids for static languages are just 
a measure of how big a problem that is, not an advantage.

It is nice that Java has gotten better, but it does /not/ support 
dynamic development the way a dynamic language does. That would be Groovy.

kt


-- 
Home? http://tilton-technology.com
Cells? http://www.common-lisp.net/project/cells/
Cello? http://www.common-lisp.net/project/cello/
Why Lisp? http://alu.cliki.net/RtL%20Highlight%20Film
Your Project Here! http://alu.cliki.net/Industry%20Application
From: Joe Marshall
Subject: Re: Java Is A Dynamic Language?
Date: 
Message-ID: <fzc07fjx.fsf@ccs.neu.edu>
Kenny Tilton <·······@nyc.rr.com> writes:

> It is nice that Java has gotten better, but it does /not/ support
> dynamic development the way a dynamic language does. That would be
> Groovy.

Java combines the dynamicity of a batch compiler with the performance
of a byte-code interpreter.  They *almost* got it.
From: Pascal Costanza
Subject: Re: Java Is A Dynamic Language?
Date: 
Message-ID: <c3nn1l$ds6$1@newsreader2.netcologne.de>
Joe Marshall wrote:

> Kenny Tilton <·······@nyc.rr.com> writes:
> 
>>It is nice that Java has gotten better, but it does /not/ support
>>dynamic development the way a dynamic language does. That would be
>>Groovy.
> 
> Java combines the dynamicity of a batch compiler with the performance
> of a byte-code interpreter.  They *almost* got it.

Since JDK 1.4, Java supports dynamic replacement of methods. If I 
correctly understand the JDK 1.5 docs, the latter even supports dynamic 
replacement of whole classes. These features are part of the debugging 
APIs, and they are made use of in Java IDEs. I think Java programmers 
have made use of this for quite some time by now.

They do not provide an update protocol yet. This means that existing 
instances of a class will continue to adhere to the old definition of a 
replaced class. For methods, currently executing methods are not 
replaced. So only newly created instances and newly invoked methods are 
affected. IIRC, there is some minimal support for breaking out of an 
executing method and restarting it in order to make the new definition 
effective, though.

More of these things seem to be available in Sun's research labs, but 
they are quite nervous about these features. That's why they lock them 
up in debugging APIs and make only some of them available, and only when 
you have the right permissions. The flexibility of CLOS + MOP is by far 
still not matched.

Nevertheless, incremental development with Java is possible nowadays. 
The compiler provided with the Eclipse IDE, for example, even allows 
executing programs that don't completely compile.


Pascal

-- 
1st European Lisp and Scheme Workshop
June 13 - Oslo, Norway - co-located with ECOOP 2004
http://www.cs.uni-bonn.de/~costanza/lisp-ecoop/
From: Gareth McCaughan
Subject: Re: Java Is A Dynamic Language?
Date: 
Message-ID: <87oeqo8ohi.fsf@g.mccaughan.ntlworld.com>
Joe Marshall wrote:

> Java combines the dynamicity of a batch compiler with the performance
> of a byte-code interpreter.  They *almost* got it.

Or, as I saw it expressed somewhere or other:

    Java. The elegant simplicity of C++. The blazing speed of Smalltalk.

-- 
Gareth McCaughan
.sig under construc
From: Pete Kirkham
Subject: Re: Java Is A Dynamic Language? [was Re: CLOS and databases]
Date: 
Message-ID: <405f4095$0$6542$cc9e4d1f@news-text.dial.pipex.com>
Kenny Tilton wrote:
> It is nice that Java has gotten better, but it does /not/ support 
> dynamic development the way a dynamic language does. That would be Groovy.
> 
> kt

No, it supports incremental development. The question got raised because 
  Erann Gat said it required all of your design to be fixed before 
coding. It has a sufficient iteration time for cases where you're far 
enough on for code-test-code, but for the initial exploration stage I 
find lisp's zero time cycle better.


Pete
From: Kenny Tilton
Subject: Re: Java Is A Dynamic Language? [was Re: CLOS and databases]
Date: 
Message-ID: <idJ7c.1597$t_4.2136380@twister.nyc.rr.com>
Pete Kirkham wrote:

> Kenny Tilton wrote:
> 
>> It is nice that Java has gotten better, but it does /not/ support 
>> dynamic development the way a dynamic language does. That would be 
>> Groovy.
>>
>> kt
> 
> 
> No, it supports incremental development. The question got raised because 
>  ...

I was reacting simply to the mid-90s being identified as the time when 
REPLs (not that I would characterize it that way, since I never touch 
that window, but I think I know what you mean) lost their advantage over 
(yes) the fine IDEs around static languages.

kt

-- 
Home? http://tilton-technology.com
Cells? http://www.common-lisp.net/project/cells/
Cello? http://www.common-lisp.net/project/cello/
Why Lisp? http://alu.cliki.net/RtL%20Highlight%20Film
Your Project Here! http://alu.cliki.net/Industry%20Application
From: Pete Kirkham
Subject: Re: Java Is A Dynamic Language? [was Re: CLOS and databases]
Date: 
Message-ID: <4060b6a9$0$6541$cc9e4d1f@news-text.dial.pipex.com>
Kenny Tilton wrote:
> I was reacting simply to the mid-90s being identified as the time when 
> REPLs (not that I would characterize it that way, since I never touch 
> that window, but I think I know what you mean) lost their advantage over 
> (yes) the fine IDEs around static languages.
> 
> kt

If I recall the dates correctly, SGI were demonstrating C++ with dynamic 
recompile & eval of running code to university labs around '95. 
Commercially, Microsoft Visual C++ version 5 had 'edit and continue', 
which came out early '97, VisualCafe for Java, again '97, had dynamic 
update of classes whilst debugging, using a custom virtual machine. The 
feature was lost in Java after version 1.2, when Sun standardized the 
debugging APIs, then came back a few years later with 1.4.  Over 94-97 
for the minor-edit-build cycle debugging that was a drag before then got 
sufficiently fast that it became interactive. So maybe mid-to-late 90s 
would be more accurate.


Pete
From: Eugene Zaikonnikov
Subject: Re: Java Is A Dynamic Language? [was Re: CLOS and databases]
Date: 
Message-ID: <680a835d.0403240139.2b55941f@posting.google.com>
Pete Kirkham <·················@cafemosaic.co.uk> wrote in message news:<························@news-text.dial.pipex.com>...
> Commercially, Microsoft Visual C++ version 5 had 'edit and continue', 
> which came out early '97

Edit and continue appeared in MSVC++ v6, and it was around 1998/99.


--
  Eugene
From: Vladimir Sedach
Subject: Re: Java Is A Dynamic Language? [was Re: CLOS and databases]
Date: 
Message-ID: <874qse841f.fsf@shawnews.cg.shawcable.net>
I've heard of an interactive C++ development environment called Sabre
that was available in the late 80s. Also, wasn't Harlequin's non-Lisp
IDE (forget the name) for C++? That was the early 90s. The problem
with most of these approaches is that they're only available while
you're debugging in the IDE, and there's really no way to ship that
with finished applications (not that they couldn't come up with one,
but then it would be just like Lisp). This is a problem for graphics
applications - for example, Wavefront's Maya (written in C++) has an
interactive interpreter for a custom-designed extension language
called MEL. The interpreter isn't fast enough for many applications,
and since there's no compiler for MEL (I suspect this is because
Greenspun's 10th is a very expensive law to comply with) what happens
very frequently is that many extensions originally prototyped in MEL
have to be re-written in C++ (which are loaded as libraries). In
contrast, compiling extensions in Izware's Mirai is just compile-file
(if you've got the developer's kit, which comes with the Allegro CL
compiler). Which brings me to my next point: this interactive
functionality is available in almost half a dozen free CL
systems. C.l.l. trolls often complain that nobody gives them useful
stuff for nothing, but this is where Lisp has C/C++ beat - all those
interactive environments are pricey (and there's not that many
available anymore). There's really nothing similar for GCC (if there
is, please tell me about it - I really could use something like that
right now).

Vladimir
From: Pekka P. Pirinen
Subject: Re: Java Is A Dynamic Language? [was Re: CLOS and databases]
Date: 
Message-ID: <ix4qs6k0ch.fsf@ocoee.cam.harlequin.co.uk>
Vladimir Sedach <·································@cpsc.ucalgary.ca> writes:
> [dynamic IDEs] Also, wasn't Harlequin's non-Lisp
> IDE (forget the name) for C++? That was the early 90s.

ITYM Lucid's Energize.  That was for C++.  Harlequin didn't buy that
from Lucid, just the Lisp (which didn't have an IDE, but is now
available with (an old version of) the LW IDE as Liquid CL).  Of
course, Harlequin did have a non-Lisp IDE as well: for Dylan -- but
obviously that was a very dynamic language from the start.  Clear now?
-- 
Pekka P. Pirinen
Don't force it, get a larger hammer.
From: Lieven Marchand
Subject: Re: Java Is A Dynamic Language? [was Re: CLOS and databases]
Date: 
Message-ID: <87vfkmvw9r.fsf@wyrd.be>
···············@globalgraphics.com (Pekka P. Pirinen) writes:

> ITYM Lucid's Energize.  That was for C++.  Harlequin didn't buy that
> from Lucid, just the Lisp (which didn't have an IDE, but is now
> available with (an old version of) the LW IDE as Liquid CL).  Of
> course, Harlequin did have a non-Lisp IDE as well: for Dylan -- but
> obviously that was a very dynamic language from the start.  Clear now?

Harlequin had a fairly nice port of their LW IDE for their
implementation of ML just before they became Xanalys. It made a very
static language like ML usable. I wonder what became of it. Did it
ever make it into a product or got bought by another company?

-- 
An amateur practices until he gets it right,
A professional practices until she can't get it wrong.
From: Pekka P. Pirinen
Subject: Re: Java Is A Dynamic Language? [was Re: CLOS and databases]
Date: 
Message-ID: <ixoeqbvgrj.fsf@ocoee.cam.harlequin.co.uk>
Lieven Marchand <···@wyrd.be> writes:
> Harlequin had a fairly nice port of their LW IDE for their
> implementation of ML just before they became Xanalys. It made a very
> static language like ML usable. I wonder what became of it. Did it
> ever make it into a product or got bought by another company?

Sadly, no.  MLWorks was briefly available from Harlequin, but after
the company was reorganized, it was dropped and no one was interested
in taking it (unlike Harlequin Dylan, which was taken up by Functional
Objects, Inc., founded by key members of the Dylan team).
-- 
Pekka P. Pirinen
The great problem with Lisp is that it is just good enough to keep us
from developing something really good.  - Alan Kay
From: Antonio Menezes Leitao
Subject: Re: CLOS and databases
Date: 
Message-ID: <pan.2004.03.25.22.30.56.544994@netcabo.pt>
Pete Kirkham <·················@cafemosaic.co.uk> writes:

> If your only purpose is to impress a Java developer audience, why are
> you not addressing the points I made?  'Duh' as a response to being
> shown a counter example to your position isn't going to knock anyone's
> socks off.
>
> ...
>
> Lisp can be better than Java, but to convince people you have to
> address their concerns, not your own.  No-one programs in Java if they
> believe language-level elegance is more important that
> practicality. Concorde was more elegant and capable on its own terms
> than any other airliner, but it couldn't survive in the market.
>

I've experienced the frustration of loving Common Lisp but being forced
to write Java because (1) the client wants it or because (2) there are
lots and lots and lots of packages for Java that simply do not exist
in Common Lisp.  Just try to google several combinations between
'Common Lisp _whatever_' and 'Java _whatever_' and watch the
difference.  And the difference tends to get bigger.  There are so
many Java programmers and so much money in the Java camp that is
really difficult to beat them with Common Lisp.

However, you can take advantage of (several) of the good Common Lisp
features and, at the same time, take advantage of the Java libraries
and frameworks that are being developed.  My proposed solution is the
Linj language which is a Common Lisp-like language that is translated
into good-looking Java code (the "good-looking" part is only for Java
programmers :-).  You can write Linj programs that take advantage of
whatever Java solutions you can get but you can also write syntactic
abstractions (I mean, Common Lisp macros) to hide all the mess.

Just to give you an example, let's take a look at the problem being
discussed (adding persistence to a program).  How many solutions exist
for Common Lisp?  Few and usually they are presented as research
papers.  How many solutions in Java?  Many and they are being used in
practice by 'normal' Java programmers.

Instead of reinventing the wheel in Common Lisp, Linj takes the
approach of using what is available "as is" but it allows you to make
it look nicer by using Common Lisp features such as macros, method
combination, generic arithmetic, etc.

Just to give you an example, I'll use the Prevayler approach to
persistence that someone suggested previously and I'll explain how to
use the Prevayler package in Linj.  There are some demos at the
Prevayler site so I'll just pick the simplest one: the idea is to
create a program that computes prime numbers but that might be aborted
and restarted again at any time.  Prevayler works by adding
persistence not to the program data but to the program actions.  This
means that each action that modifies the state of the program must be
reified into the Command pattern (recent versions use the Transaction
interface), which is a PITA because it makes your code look ugly.  In
Common Lisp, we use macros to hide patterns, so that's what we will do
here.

Here is the program: (I added a few obvious comments...)

----------------------------------------------------------------
(import org.prevayler.*) ;;We will use the prevayler package

(defun main ()
  (let ((prime-keeper (new 'Vector)))        ;;a generic Java container
    (add prime-keeper 2)
    (let ((prevayler                         ;;make it prevalent
            (prevail prime-keeper "PRIMES"))
	  (prime-candidate          ;;extract the last generated prime
            (1+ (the long (last-element prime-keeper)))))
      (loop
       (when (prime-p prime-candidate)
         ;;make a transaction to save this prime
	 (keep-prime prevayler prime-candidate) 
	 (format t "New prime found: ~A.~%" prime-candidate))
       (incf prime-candidate)))))

;;The next function just tests if a given number is prime

(defun prime-p (number)
  (declare (long number))
  (if (or (<= number 2)
	  (zerop (rem number 2)))
    nil
    (let ((square (ceiling (sqrt number))))
      (do ((factor 3 (+ factor 2)))
	  ((> factor square) t)
	(when (zerop (rem number factor))
	  (return nil))))))

;;The only missing part is the "transaction" keep-prime:

(deftransaction keep-prime ((store Vector) number-to-keep)
  (add store number-to-keep))
----------------------------------------------------------------

The previous program uses the macros 'prevail' and 'deftransaction'
that I will explain latter.

Linj can translate the previous program into the following Java
program.

----------------------------------------------------------------
import java.io.IOException;
import java.util.Date;
import java.util.Vector;
import linj.Bignum;
import org.prevayler.*;

public class PrimesVector extends Object {

    // methods

    public static void main(String[] outsideArgs) throws IOException, ClassNotFoundException {
        Vector primeKeeper = new Vector();
        primeKeeper.add(Bignum.valueOf(2));
        Prevayler prevayler = PrevaylerFactory.createPrevayler(primeKeeper, "PRIMES");
        long primeCandidate = ((Number)primeKeeper.get(primeKeeper.size() - 1)).longValue() + 1;
        while (true) {
            if (primeP(primeCandidate)) {
                keepPrime(prevayler, Bignum.valueOf(primeCandidate));
                System.out.print("New prime found: " + primeCandidate + "." + '\n');
            }
            ++primeCandidate;
        }
    }

    public static boolean primeP(long number) {
        if ((number <= 2) || ((number % 2) == 0)) {
            return false;
        } else {
            double square = Math.ceil(Math.sqrt(number));
            for (int factor = 3; factor <= square; factor = factor + 2) {
                if ((number % factor) == 0) {
                    return false;
                }
            }
            return true;
        }
    }

    public static void keepPrime(Prevayler store, Object numberToKeep) {
        store.execute(new KeepPrime(numberToKeep));
    }
}


class KeepPrime extends Object implements Transaction {

    // constructors

    public KeepPrime(Object numberToKeep) {
        this.numberToKeep = numberToKeep;
    }

    // methods

    public void executeOn(Object prevalentSystem, Date date) {
        Vector store = (Vector)prevalentSystem;
        store.add(numberToKeep);
    }

    // slots

    protected Object numberToKeep;
}
----------------------------------------------------------------

You can now compile it and execute it:

----------------------------------------------------------------
$ javac PrimesVector.java

$ java PrimesVector
New prime found: 3.
New prime found: 5.
New prime found: 7.
New prime found: 11.
...
New prime found: 409.
New prime found: 419.
[CONTROL-c, aborting the computation]

$ java PrimesVector
Reading PRIMES/0000000000000000001.transactionLog...
New prime found: 431.
New prime found: 433.
...
New prime found: 887.
New prime found: 907.
[CONTROL-c, aborting the computation]

$ java PrimesVector
Reading PRIMES/0000000000000000001.transactionLog...
Reading PRIMES/0000000000000000082.transactionLog...
New prime found: 911.
New prime found: 919.
...
New prime found: 1151.
New prime found: 1153.
[CONTROL-c, aborting the computation]

$ java PrimesVector
Reading PRIMES/0000000000000000001.transactionLog...
Reading PRIMES/0000000000000000082.transactionLog...
Reading PRIMES/0000000000000000155.transactionLog...
New prime found: 1163.
New prime found: 1171.
New prime found: 1181.
...
----------------------------------------------------------------

Quite simple, IMHO.

What's missing?  The above mentioned macros 'prevail' and
'deftransaction'.  The good news is that they are just plain Common
Lisp macros:

----------------------------------------------------------------
(defmacro prevail (expr &optional (name "prevail"))
  `(in (the prevayler-factory)
       (create-prevayler ,expr ,name)))

(defmacro deftransaction (name ((store store-class) &rest arglist) &body body)
  `(progn
     (defun ,name (,store ,@arglist)
       (declare (prevayler store))
       (execute ,store (new ',name ,@(mapcar #'extract-name&type arglist))))
     
     (defclass ,name (transaction object)
       ,(mapcar #'(lambda (arg)
		    `(,arg))
		arglist)
       (:body
	(defnew ,arglist 
	  ,@(mapcar #'(lambda (arg)
			`(setf (slot-value this ',arg) ,arg))
		    arglist))
	(defmethod execute-on (prevalent-system/object date/date)
	  (let ((,store (the ,store-class prevalent-system)))
	    ,@body))))))
----------------------------------------------------------------

Although there are some Linj-specific code fragments, it's mostly
Common Lisp.

The above macros are just a simple attempt at hiding all that annoying
but necessary Java code.  You could use other strategies, of course.

I'm planning to release Linj but I'm still unsure about the best
licence.  Suggestions are welcome.

Best regards,

Ant�nio Leit�o.

[PS: I'm afraid I have a problem in my news feed.  I couldn't see my own
article so I decided to post it a second time.  Sorry if you
have already seen this.]
From: André Thieme
Subject: Re: CLOS and databases
Date: 
Message-ID: <c4032t$448$1@ulric.tng.de>
Antonio Menezes Leitao wrote:

> I'm planning to release Linj but I'm still unsure about the best
> licence.  Suggestions are welcome.

I am really looking forward to it!
If we get tools to generate code for Java, C++, C#, Perl, php and Python
then I think most Lispers will have the opportunity to use CL in their
jobs (and noone will find out about it *g*).
It only should be given, that these tools allow a similar productivity
as one would without them (or better).


Andr�
--
From: Thomas A. Russ
Subject: Re: CLOS and databases
Date: 
Message-ID: <ymik717sfo0.fsf@sevak.isi.edu>
=?ISO-8859-1?Q?Andr=E9_Thieme?=  <······································@justmail.de> writes:

> 
> Antonio Menezes Leitao wrote:
> 
> > I'm planning to release Linj but I'm still unsure about the best
> > licence.  Suggestions are welcome.
> 
> I am really looking forward to it!
> If we get tools to generate code for Java, C++, C#, Perl, php and Python
> then I think most Lispers will have the opportunity to use CL in their
> jobs (and noone will find out about it *g*).
> It only should be given, that these tools allow a similar productivity
> as one would without them (or better).

Well, if you want to investigate tools somewhat like that, I could
direct you to our Stella system.  It is not a Common Lisp to Java or C++
translator, but it does allow you to work in a restricted Lisp-like
language while delivering native Java or C++ or even Common Lisp code.

   http://www.isi.edu/isd/LOOM/Stella/index.html

Working with the Common Lisp version, you get all of the dynamic linking
and redefinition features that one normally expects.  The input syntax
is familiar S-expressions and macros are supported.  The object system
is much more constrained than CLOS, though, because of a design goal to
be able to easily translate to a single-inheritance, single-dispatch
language.

C# is not available (yet), but it probably wouldn't be hard to produce,
based on the Java translator.  The weakest part is actually the
documentation for the system.

Stella is an Open Source project, available under a choice of three
licensing options:  GPL, LGPL or Mozilla.

-- 
Thomas A. Russ,  USC/Information Sciences Institute
From: Pete Kirkham
Subject: Re: CLOS and databases
Date: 
Message-ID: <40647176$0$3302$cc9e4d1f@news-text.dial.pipex.com>
I've also been playing on some similar themes, and come to the 
conclusion that to target Java/.net/Objective-C or C++ has too much of 
an impedance match to use ANSI CL as source language.

Every library in the target languages (or for that matter python or 
haskell) has a list model as a thing than has functions to access it's 
members sequentially. Null and () are different. Even though you can add 
wrappers and unwrappers to map cons'd lists onto functional lists, 
automating them is a drag and the end code looks messy and runs slower 
than pure Java; this gets very complicated if you are modifying a list 
you have a reference to the head of elsewhere. It is also nice to use 
the same iteration forms on functional lists, for example representing 
the output of a streaming parser as a list of symbols- you don't want to 
hold a 8GB AST in memory if you're only forward iterating over it's 
contents, but you don't want to have to rewrite your code for the cases 
where you do have the thing in memory.

The object systems in the target languages doesn't match CLOS. This 
means if you want to use objects, you have to may from something other 
than CLOS to the target language, or you can get lots of non-first arg 
dispatch bugs. You can generate warnings for this quite easily at the 
compile stage, if you also have a metaobject system in your generator. 
As the computers on most people's desktops look like they are going to 
be running a single dispatch object system as the core of their 
operating system in a couple of years, downgrading from lisp's 
capability is possibly the only pragmatic option. However, providing 
auto-generation of the boilerplate for double dispatch is fairly 
trivial, in the cases where the classes are in your control, so that can 
be done transparently in most cases without a loss of conciseness.


Another thing I've played with is a lisp interface to a byte code 
library, which had some success flattening OOT-OO Java and moving 
branchs forward, detecting like clauses and other patterns as a 
optimization process. That's implemented in Java, but with a lisp as the 
control language, largely as I'd started it as a GUI based Java project, 
but then decided that it would be easier to use with a command line and 
scripting language, and if it's going to contain a scripting language 
you may as well make it lisp. I'm planning to revisit that soon (I'm 
writing an ASN.1 library for Java and want to be able to allow 
flattening for the binary encoding cases but give a capability for 
runtime configuration so you can read legacy file formats and arbitrary 
XML), but is a bit too buggy for serious use right now, partly as I 
tried to make its lisp too like common lisp so it ended up with lots of 
impedance-management hacks, and more functionality than I could really 
be bothered testing. I didn't want to reuse an extant cl implementation 
as I hope to be able to reuse my little-lisp-on-java as a control 
language for other Java tools.


Pete
From: Antonio Menezes Leitao
Subject: Re: CLOS and databases
Date: 
Message-ID: <pan.2004.03.27.17.07.18.624499@evaluator.pt>
On Fri, 26 Mar 2004 18:07:50 +0000, Pete Kirkham wrote:

> I've also been playing on some similar themes, and come to the 
> conclusion that to target Java/.net/Objective-C or C++ has too much of 
> an impedance match to use ANSI CL as source language.

That's specially true when you try to produce readable code in the
target language.  But remember that Linj is not ANSI CL. Linj is a
Common Lisp-like language.  My claim is that with some mild
restrictions in the source language, you can reduce the impedance
mismatch with the target language.

> Every library in the target languages (or for that matter python or 
> haskell) has a list model as a thing than has functions to access it's 
> members sequentially. Null and () are different.

Linj implements pairs just like in Common Lisp.  They are not
translated into Java containers such as ArrayList or Vector, they are
translated just as a user-defined class.  Here is (part of) the
definition of the cons type in Linj:

(package linj)

(defclass cons ()
  ((car :accessor car :initarg :car)
   (cdr :accessor cdr :initarg :cdr)))

(defconstant +empty-list+ (make-instance 'cons))

(setf (car +empty-list+) +empty-list+
      (cdr +empty-list+) +empty-list+)

(defmethod endp (this)
  (eq this +empty-list+))

...

(defmethod find (elem (list cons) &key (test #'eql) (key #'identity))
  (cond ((endp list)
	 null)
	((funcall test elem (funcall key (first list)))
	 (first list))
	(t
	 (find elem (rest list) :test test :key key))))
...
-----------------------------------------------------------------

This class definition is translated into:

-----------------------------------------------------------------
package linj;

public class Cons extends Object {

    public Cons(Object car, Object cdr) {
        this.car = car;
        this.cdr = cdr;
    }

    public Object car() {
        return car;
    }

    public Object setfCar(Object car) {
        return this.car = car;
    }
...
    public boolean endp() {
        return this == EMPTY_LIST;
    }
...
    public Object find(Object elem, Predicate2 test, Function key) {
        if (this.endp()) {
            return null;
        } else if (test.funcall(elem, key.funcall(this.first()))) {
            return this.first();
        } else {
            return this.rest().find(elem, test, key);
        }
    }
...
   public static final Cons EMPTY_LIST = new Cons(null, null);

   static {
        EMPTY_LIST.setfCar(EMPTY_LIST);
        EMPTY_LIST.setfCdr(EMPTY_LIST);
    }
}
...
-----------------------------------------------------------------

Like you said, Linj also treats null and () as different entities and
I like it that way.  However, _when these values are received in a
context where we are expecting booleans_ they are treated the same
and, just like in Common Lisp, () is also the false value.  Consider
the following fragment/translation:

(defun foo (a b c)
  (declare (boolean a) (cons b) (object c))
  (not (and a b c)))
-----------------------------------------------------------------
    public static boolean foo(boolean a, Cons b, Object c) {
        return ! (a && (! b.endp()) && (c != null));
    }

This allows you to write the traditional Common Lisp pattern of using
the empty list as false value.  Consider the following case (I'll drop
the declare form and use a more compact equivalent):

(defun bar (elem1 elem2 list/cons)
  (let ((tail (member elem1 list)))
    (if (member elem2 tail)
      elem1
      elem2)))
-----------------------------------------------------------------
    public static Object bar(Object elem1, Object elem2, Cons list) {
        Cons tail = list.memberKey(elem1, null, null, 1);
        if (! tail.memberKey(elem2, null, null, 1).endp()) {
            return elem1;
        } else {
            return elem2;
        }
    }

Note the different uses of the member function.  In the first, we are
expecting a list as result.  In the second we are expecting a boolean.
My claim is that the boolean context is the only situation where you
want to treat 'null' and '()' (and 'nil') as the same entity.

Although Linj has a list data-type that is very similar to Common
Lisp's lists, nothing prevents you of using other Java containers.
They have different operations and a different use model, but that's
something you must know when you use them.

> Even though you can add wrappers and unwrappers to map cons'd lists
> onto functional lists, automating them is a drag and the end code
> looks messy and runs slower than pure Java; this gets very
> complicated if you are modifying a list you have a reference to the
> head of elsewhere. 

As I said, they have different use models.  If you use the 'cons' data
type, you get Lisp lists.  If you use the 'ArrayList', 'Vector',
'LinkedList' or any other Java API data type, you must stick to that
data type operations.  No impedance mismatch here.

> It is also nice to use the same iteration forms
> on functional lists, for example representing the output of a
> streaming parser as a list of symbols- you don't want to hold a 8GB
> AST in memory if you're only forward iterating over it's contents,
> but you don't want to have to rewrite your code for the cases where
> you do have the thing in memory.

They don't have the same iterations forms.  In the 'cons' data type,
you have (restricted forms of) mapc, mapcar, dolist, etc.  In the Java
API data types, you have the Java iterations forms such as Enumeration
and Iterator.

However, one of the things I like most about Linj is that you can
define macros that can use type information (something that Common
Lisp does not have).  We can define a 'for-each' macro that looks at
the type of the object being iterated and expands into the correct
form.  Here is an example, using the Vector' 'elements' method (it
returns an Enumeration):

(defun print-it (x/Vector)
  (for-each (e (elements x))
    (format t "~A~%" e)))
--------------------------------------------------------------
    public static void printIt(Vector x) {
        Enumeration iter = x.elements();
        while (iter.hasMoreElements()) {
            Object e = iter.nextElement();
            System.out.println(e);
        }
    }

If you change the function to use the Iterator interface (using the
Vector' 'iterator' method), you get:

(defun print-it (x/Vector)
  (for-each (e (iterator x))
    (format t "~A~%" e)))
--------------------------------------------------------------
    public static void printIt(Vector x) {
        Iterator iter = x.iterator();
        while (iter.hasNext()) {
            Object e = iter.next();
            System.out.println(e);
        }
    }

Now, we decide that, after all, the parameter 'x' is a list:

(defun print-it (x/cons)
  (for-each (e x)
    (format t "~A~%" e)))
--------------------------------------------------------------
   public static void printIt(Cons x) {
        for (Cons list = x; ! list.endp(); list = list.rest()) {
            Object e = list.first();
            System.out.println(e);
        }
    }

The macro is not difficult.  Here's a quick attempt (don't bother yet
with potential name capture):

(def-linj-macro statement (for-each (?var ?form/expression) . ?body/statement-list)
  (let ((form-type (get-type ?form)))
    (cond ((cons-type-p form-type)
	   `(dolist (,?var ,?form) . ,?body))
	  ((iterator-type-p form-type)
	   `(let ((iter ,?form))
	      (while (has-next iter)
		(let ((,?var (next iter))) . ,?body))))
	  ((enumeration-type-p form-type)
	   `(let ((iter ,?form))
	      (while (has-more-elements iter)
		(let ((,?var (next-element iter))) . ,?body))))
	  (t
	   (error "Unknown type for iteration ~A" form-type)))))

Of course, if you prefer, you can make the macro more sophisticated by
looking at the implemented interfaces and searching for an iteration
protocol such as java.util.List.  These macros, in fact, can have
access to the entire AST of the Linj program.

>  The object systems in the target
> languages doesn't match CLOS. This means if you want to use objects,
> you have to may from something other than CLOS to the target
> language, or you can get lots of non-first arg dispatch bugs. You
> can generate warnings for this quite easily at the compile stage, if
> you also have a metaobject system in your generator.  As the
> computers on most people's desktops look like they are going to be
> running a single dispatch object system as the core of their
> operating system in a couple of years, downgrading from lisp's
> capability is possibly the only pragmatic option. However, providing
> auto-generation of the boilerplate for double dispatch is fairly
> trivial, in the cases where the classes are in your control, so that
> can be done transparently in most cases without a loss of
> conciseness.

That's more or less what Linj does.  Currently, we only have single
dispatch _but_ it doesn't need to be on the first argument.  To
implement the usual Common Lisp functions you sometimes want to
'dispatch' on a different argument.  For example, on the 'cons' class,
you would like to define methods such as 'member', 'mapcar', 'remove',
etc., where the 'receiver' is the second argument of the call.  This
allows you to write '(member e l)' and to translate it to
'l.member(e)' in Java.  Besides, Linj implements a simplified form of
method combination (including :before, :after and :around) so we
support a nice fragment of CLOS.

In general, single dispatch solves most of the problems but for
certain cases, we will really need multiple dispatch.  I have plans to
add multiple dispatch but it'll have to wait until I have some more
time.

The truth is that Linj is used because of the huge Java libraries
(otherwise, I would have been using Common Lisp) or because the client
wants Java (someone told him it's good to have Java).  These two
reasons reduce the usefulness of having full Common Lisp capabilities
in Linj: we would not be able to take advantage of them while dealing
with Java libraries and it would be harder to translate them into
readable Java code.

Thanks for your comments.

Antonio Leitao.
From: Pete Kirkham
Subject: Re: CLOS and databases
Date: 
Message-ID: <4065da32$0$6552$cc9e4d1f@news-text.dial.pipex.com>
Antonio Menezes Leitao wrote:
> My claim is that the boolean context is the only situation where you
> want to treat 'null' and '()' (and 'nil') as the same entity.
I think I'd agree to that.

> However, one of the things I like most about Linj is that you can
> define macros that can use type information (something that Common
> Lisp does not have).  
Macro expansion on expression type looks like it covers the iteration 
(and a few other cases) nicely, though it means you still have two 
libraries for (say) sorting a list.

> we support a nice fragment of CLOS.
I found your manual and would agree.

You use almost the same name mangling scheme as I do; though I hadn't 
thought to put the types after the names of arguments with a slash.

As I'm interested in using the thing at runtime as a scripting language, 
in my interpreter I've used the Java bean conventions to map accessors, 
so that:
  (when (not (visible frame)) (setf (visible frame) #t) (pack frame))

becomes (the equivalent of compiling and running):
  if (!frame.isVisible()) {frame.setVisible(true); frame.pack(); }

rather than
  if (!frame.visible()) {frame.setfVisible(true); frame.pack(); }

(assuming your translation that generates the accessor method name from 
slot name is used in a symmetric manner).

It only tries getFoo() and isFoo() if foo() is undefined.

There's a similar mapping for named init-args and extra method args, 
applied after for init and before for methods.
  (defun foo () (make-instance foo "red" "apples" :bar 1 :baz 42))
->
  static Foo foo () {
   Foo foo = new Foo ("red", "apples");
   foo.setBar(1);
   foo.setBaz(42);
   return foo;
  }
The extra method args are applied before calling the method, so you can have
  (draw graphics shape :color red
    :stroke (once (make-instance basic-stroke 7)))
and it'll call setColor() and setStroke() before calling draw(shape), 
and (when I get round to implementing it) use a static final field to 
cache for the once value.

I also use a different mechanism to simulate conditions:
   Conditions.raise(new Error("This is completely wrong"));

Where the implementation of Conditions.error passes the error to a list 
of handlers stored in a thread local variable, so it's only thrown if 
either the handler for the signalling thread is null or the no handler 
in the list handles the error. This only deals with the exceptions in 
the code you've written, not any from called functions, but that can't 
be helped. It's mainly used by the interpreter for the debugger to hook 
into, so it might not be a consideration with what you're doing.

For &rest I use the form proposed for Java varargs (pass an array of 
objects & have a "Varargs" attribute to the method in the bytecode) 
rather than passing a cons. If you're not looking at targeting 1.5 or 
producing Java that ships without your runtime then that's not important.


Pete
From: Antonio Menezes Leitao
Subject: Re: CLOS and databases
Date: 
Message-ID: <pan.2004.03.28.01.11.07.319448@evaluator.pt>
On Sat, 27 Mar 2004 19:46:58 +0000, Pete Kirkham wrote:

> You use almost the same name mangling scheme as I do; though I hadn't 
> thought to put the types after the names of arguments with a slash.

You can also use the traditional Common Lisp 'declare' form but given
the fact that you must use it more often than in Common Lisp I decided to
invent a nicer syntax.  Some of my friends do not like it but
it allows you to write code a bit faster. Another reason is that I don't
like the aestetics of declare forms.

> As I'm interested in using the thing at runtime as a scripting language,
> in my interpreter I've used the Java bean conventions to map accessors,
> so that:
>   (when (not (visible frame)) (setf (visible frame) #t) (pack frame))
> 
> becomes (the equivalent of compiling and running):
>   if (!frame.isVisible()) {frame.setVisible(true); frame.pack(); }
> 
> rather than
>   if (!frame.visible()) {frame.setfVisible(true); frame.pack(); }
> 
> (assuming your translation that generates the accessor method name from
> slot name is used in a symmetric manner).
> 
> It only tries getFoo() and isFoo() if foo() is undefined.

On an early phase of the Linj development I had a similar approach,
but I gave up because I found too much inconsistency in the Java APIs.
Currently, I reserve the (setf (accessor ...) ...) for my own methods.
For the Java APIs, I use the (set-visible frame t) instead of the 
(setf (visible frame) t).  Maybe I'll allow the user to specify which 
of the approaches to use.
 
> There's a similar mapping for named init-args and extra method args,
> applied after for init and before for methods.
>   (defun foo () (make-instance foo "red" "apples" :bar 1 :baz 42))
> ->
>   static Foo foo () {
>    Foo foo = new Foo ("red", "apples");
>    foo.setBar(1);
>    foo.setBaz(42);
>    return foo;
>   }
> The extra method args are applied before calling the method, so you can
> have
>   (draw graphics shape :color red
>     :stroke (once (make-instance basic-stroke 7)))
> and it'll call setColor() and setStroke() before calling draw(shape),
> and (when I get round to implementing it) use a static final field to
> cache for the once value.

That's something very interesting.  And it doesn't look hard to
implement in Linj.  However, Linj tries hard to implement Common Lisp
ordinary lambda lists and this will force the programmer to
declare all the keyword parameters.  Moreover, some code fragments will
be hard to translate to readable Java.  Here is one example:

(add panel (make-instance label "text" :alignment ...))

What will be the Java generated code in this case?

> I also use a different mechanism to simulate
conditions:
>    Conditions.raise(new Error("This is completely wrong"));
> 
> Where the implementation of Conditions.error passes the error to a list
> of handlers stored in a thread local variable, so it's only thrown if
> either the handler for the signalling thread is null or the no handler
> in the list handles the error. This only deals with the exceptions in
> the code you've written, not any from called functions, but that can't
> be helped. It's mainly used by the interpreter for the debugger to hook
> into, so it might not be a consideration with what you're doing.

Yes.  Once again, my main goal was to let the client think that I wrote
tha Java code by hand.  This decision forced me to use 'normal'  Java code
almost exclusively.  Regarding exceptions, I must confess that I
became completely fed up with Java checked exceptions and, as a result, I
decided to implement the propagation of Java checked exceptions to the
caller. Either you deal with the exception or you let it go up the
caller chain.  If you never catch exceptions you end up with the top
level methods with a nice list of throws :-) 

> For &rest I use the form
proposed for Java varargs (pass an array of
> objects & have a "Varargs" attribute to the method in the bytecode)
> rather than passing a cons. If you're not looking at targeting 1.5 or
> producing Java that ships without your runtime then that's not
> important.
> 

To implement the Common Lisp &rest, I decided to go the Common Lisp way:
the caller passes a list (made of cons instances) and you can do whatever
you want with it. I might invent another lambda list keyword to implement
vargars but, in fact, my best client needed Java 1.1 so I could not depend
on the advanced features being proposed for java.

Thanks again for you comments.  Lots of good ideas.

Antonio Leitao.
From: Pete Kirkham
Subject: Re: CLOS and databases
Date: 
Message-ID: <4066bbad$0$6557$cc9e4d1f@news-text.dial.pipex.com>
Antonio Menezes Leitao wrote:
>  Here is one example:
> 
> (add panel (make-instance label "text" :alignment ...))
> 
> What will be the Java generated code in this case?

In bytecode you use dup (duplicate the last item on the operand stack), 
an in the interpreter it's handled as part of the call to makeInstance. 
It doesn't translate to Java-the-language without adding a temporary 
variable.


Pete
From: Cameron MacKinnon
Subject: Re: CLOS and databases
Date: 
Message-ID: <4MOdnQBfduq-dsDdRVn_iw@golden.net>
Pete Kirkham wrote:
>  > Where's Erik when we need him?
> 
> Could you explain the reference?

Erik Naggum formerly posted a lot on c.l.l. He added a lot of value, 
tended to have a polarizing influence on the newsgroup, and didn't 
suffer fools gladly, if at all. I started reading the group during a 
hiatus of his, and was compelled by the many references to him to seek 
out and read many of his old posts. He knows his Lisp, and he's better 
at natural language processing (i.e. reading comprehension) than most.

http://groups.google.com/groups?q=group%3Acomp.lang.lisp+%22erik+naggum%22

The above link unfortunately skews toward postings about Eric, rather 
than by him, but you can keep scrolling.

-- 
Cameron MacKinnon
Toronto, Canada
From: simon
Subject: Re: CLOS and databases
Date: 
Message-ID: <m3vfky9ed4.fsf@localhost.localdomain>
Cameron MacKinnon <··········@clearspot.net> writes:
> http://groups.google.com/groups?q=group%3Acomp.lang.lisp+%22erik+naggum%22
> 
> The above link unfortunately skews toward postings about Eric, rather than
> by him, but you can keep scrolling.

A search like:

http://groups.google.com/groups?as_ugroup=comp.lang.lisp&as_uauthors=erik%20naggum

specifies the author instead of posts containing the name, and should save you 
some scrolling...

cheers,
Simon 
From: ·········@random-state.net
Subject: Re: CLOS and databases
Date: 
Message-ID: <c3iqnm$5ec8e$1@midnight.cs.hut.fi>
Pete Kirkham <·················@cafemosaic.co.uk> wrote:

> find that once you are dealing with over a hundred lines of code you
> have to use an editor for lisp too, so the difference today is do I
> drag&drop (load "foo.lisp")  into the rep loop or hit the
> recompile-and-run button.

Are quite sure you're not missing anything here?

Cheers,

 -- Nikodemus

PS. I'm definitely not up to speed on Java IDEs, but is it really
commonplace to replace individual methods without recompiling significant
parts of the whole project -- and within milliseconds at that? I obviously
need to not only get out more, but get a new box. ;-)
From: Pete Kirkham
Subject: Re: CLOS and databases
Date: 
Message-ID: <405d9d97$0$6541$cc9e4d1f@news-text.dial.pipex.com>
·········@random-state.net wrote:
> PS. I'm definitely not up to speed on Java IDEs, but is it really
> commonplace to replace individual methods without recompiling significant
> parts of the whole project -- and within milliseconds at that? I obviously
> need to not only get out more, but get a new box. ;-)

In OO programming, the method implementation is independent of the 
interface. In rapid development, each method is developed in isolation 
against its unit tests. The unit test exercises the interface, so 
doesn't need recompilation when the method change. Most of the 
iterations for a single method require the only the recompilation of the 
class that the method is in. To fire up Ant, recompile a single class 
and run a dozen unit tests on it is typically 200-300ms on my G4 2x1.42. 
That is the cycle time for most of my development; not significantly 
longer compared to running the tests in the REPL loop. In either 
environment, you spend >99% time editing the code, not building or 
running it.

If I do the same in an IDE rather than an emacs clone, or am using an OS 
which doesn't cache the JVM compiled bytecode image, it can take half a 
minute, but that's IDEs/Windoze for you. I use an IDE as a glorified 
debugger/object inspector if I get a bug which doesn't show in the unit 
tests.

Once you get to interactions between classes, the cycle time goes up, 
but if your assembling your application from proven components, and your 
overall architecture is alright, then you don't spend too much time in 
the unit assembly stages.

If changes to a method require a global rebuilt, you're not doing OO 
right, and need to refactor. Refactoring takes longer, and isn't 
supported by the language (which is one point where using lisp can be a 
winner over pure Java; one of the things I'm playing with is a 
refactoring tool that's scriptable in lisp) but that sort of 
architectural change happens less frequently and requires you to spend 
time thinking whatever your environment is, so isn't really part of the 
smallest iterative loop.


Pete
From: a
Subject: Re: CLOS and databases
Date: 
Message-ID: <fL27c.73034$vn.217330@sea-read.news.verio.net>
"Erann Gat" <·········@jpl.nasa.gov> wrote in message
·······························@k-137-79-50-101.jpl.nasa.gov...
>
> I'm working on a simple object database built on top of a relational
> database.  My current design is to have a "storable" mixin class which
> defines two methods, STORE and RETRIEVE, which do the obvious things.
>
> A problem with this simple design is that it places a burden on the user
> to keep track of the relative states of the objects in memory and in the
> DB, and to decide when to STORE and RETRIEVE them.  It would be nice to
> make this transparent so that any reference to a slot of a STORABLE object
> would transparently synchronize to the DB.  I had envisioned implementing
> this using a :before method on the slot-value  and (setf slot-value)
> methods which would check to make sure everything was in sync.
>
> Is there a better way to do it?  Is this a job for the MOP?
>
> My goal here is not only to make something functional, but also to
> highlight the power of CLOS with something that will really knock the
> socks off the Java people, so I really want to do this the Right Way.
>
> E.

There is a reason ACID relational databases have
begin-transaction/end-transaction constructs and databases without them are
weaker. Suppose I'm using a database of images and there is a failure when
the program is halfway through the modification of a large image. What is
the proper state of the database when the program is restarted? Your
persistence engine cannot know when the algorithm has completed the image
manipulation, nor can the engine know when there is a group of objects
modified separately but the changes for which must all hit the database or
none of them hit it. The programmer has to specify transaction end points to
delineate points of consistency between STORABLE objects in the application.

I suppose an argument could be made for implicit begin-transactions when a
STORABLE slot-value changes, although an argument could be made that
requiring the begin will help catch bugs where the programmer did not intend
to enter transaction state. Additionally, if you are flushing transactions
to the relational database as updates occur in the program, then you are
leaving the relational database with an open transaction state until the
end-transaction is called. That is not a nice way to play with the
database's other users and is especially bad if the programmer's bug caused
an implicit begin-transaction. Consider the image application again. What if
I want to apply a filter to see if I like it? If I don't, I undo. Is there a
reason to flush the image to the database before the user accepts the
change? I vote for the explicit begin-transaction.

You might explore a (flush) which does (with-transaction (db)
(store-all-modified-storable-objects)) but I'd also like to have
(with-transaction (db) (store-storable-objects <object>*)).

It's an interesting and practical application. Good luck.
From: Will Hartung
Subject: Re: CLOS and databases
Date: 
Message-ID: <c3nsfo$29dv5j$1@ID-197644.news.uni-berlin.de>
"a" <···@def.gh> wrote in message
··························@sea-read.news.verio.net...

> There is a reason ACID relational databases have
> begin-transaction/end-transaction constructs and databases without them
are
> weaker. Suppose I'm using a database of images and there is a failure when
> the program is halfway through the modification of a large image. What is
> the proper state of the database when the program is restarted? Your
> persistence engine cannot know when the algorithm has completed the image
> manipulation, nor can the engine know when there is a group of objects
> modified separately but the changes for which must all hit the database or
> none of them hit it. The programmer has to specify transaction end points
to
> delineate points of consistency between STORABLE objects in the
application.

The biggest complaint I have is that simply updating/inserting a row with
multiple indexes must in itself be a transaction.

A single record update is nothing more than a block write, and is ALMOST
atomic. The risk of a write failure is quite low.

But throw in indexes, and a you are now talking several block writes, and
depending on how the blocks are flushed, can easily leave an index corrupted
if it fails at a particularly bad point.

So, just to guarantee that a single update is done properly, you need to
have the foundations of a transactional system in place to be able to, at a
database level, atomically update the record and its indexes.

There are few things more annoying than having to rebuild database indexes.
In Dark Days of Yore where I worked on ISAM systems, rebuilding indexes was
du jour for fixing problems. Step one: Rebuild indexes.

I understand that modern mySQL has transactions as an option, and the fact
that it's a server process will ideally help isolate application crashes
from corrupting the DB. But mySQL has other "problems" that make me avoid it
as well.

HOWEVER, as a bone head simple data store, i.e. a higher level Berkley DB,
I'm sure for Eranns needs it's acceptable.

Regards,

Will Hartung
(·····@msoft.com)
From: Plamen Stamov
Subject: Re: CLOS and databases
Date: 
Message-ID: <405d0050@news01.datazug.ch>
Erann Gat wrote:
> I'm working on a simple object database built on top of a relational
> database.  My current design is to have a "storable" mixin class which
> defines two methods, STORE and RETRIEVE, which do the obvious things.
> 
> A problem with this simple design is that it places a burden on the user
> to keep track of the relative states of the objects in memory and in the
> DB, and to decide when to STORE and RETRIEVE them.  It would be nice to
> make this transparent so that any reference to a slot of a STORABLE object
> would transparently synchronize to the DB.  I had envisioned implementing
> this using a :before method on the slot-value  and (setf slot-value)
> methods which would check to make sure everything was in sync.
> 
> Is there a better way to do it?  Is this a job for the MOP?
> 
> My goal here is not only to make something functional, but also to
> highlight the power of CLOS with something that will really knock the
> socks off the Java people, so I really want to do this the Right Way.
> 
> E.

Hello,

I would not like to discourage you in your enterprise, but I think that 
to "really knock the socks off the Java people", you will have to 
implement something more difficult than that.

Current O/R mapping products (not only commercial ones) include more or 
less the following functionality :
- ACID transactions. In multithreaded environments. Because it usually 
matters;
- several mapping schemas for classes, because of the different 
performace characteristcs for different access patterns to the 
objects/tables, and as second because sometimes people like to access 
legacy databases, whose datamodel have the structure of cobol 
copy-members and as such is hardly even relational...) and for simple 
types (because some legacy applications store a boolean as 1 and 0 in a 
field of type VARCHAR(1)...) ;
- support different distribution models (C/S, multitier, in cluster or 
not) whith all implications for distibuted transactions and caching;
- some method for making the mapping process easier (GUI, XML etc. - 
this is not to say that it is a good solution, but better that nothing :) ;
- support for caching (and sometimes in a cluster);
- support some kind of may be optimizable (in terms of caching ans 
translation to SQL) query language;
- the possibility to tune the access methods of the mapping library to 
specific contexts (againg because of performance);
- support for all major databases (with the possibility to let you write 
your own SQL, for the cases where the tool does this in a too dumb or 
incompatible way);
- add some more less important functionality

As a user you have the possibility to choose between several (I know of 
at least 15) products with licensing costs between $0 and several 
thousends per seat and/or processor (application server not included :) 
. With documentation between 0 and up to 800 pages. With support between 
0 and somehow usable. With performance between 0 and good in the context 
of having a Java O/R layer in your application. With more or less 
portability between JVMs, application servers and databases.

Even if every single future is may be trivial, all together are by far 
not. Some of the complexity comes from the design of the JVM, Java and 
standards like JDBC, EJB and JDO. But the rest comes from questions not 
related to Java directly (like distributed transactions and caching). 
Not to mention the trade-offs of using O/R mapping in general and in 
Java in particular. Actually some of the problems are in Java easier 
than in CL, for example you haveto think more about possible mapping 
schemas, because you can put in a slot much more things than in Java.

So, to impress a Java people, even if you don't manage to do it the 
right way, you would have to at least implement enought functionality 
just because in the Java world it is allready there. Not to say, that I 
have a lot of positive feelings about the Java world - I just happen to 
know somehow the market of O/R mapping tools and some of the 
expectations of their users. (Commenting these expectations would be 
actually a funny off-topic :)

How easy it is to implement a simple O/R mapping library is allready 
demonstrated by UnCommonSQL and the like (I'm placing it before 
CommonSQL not because of it's qualities, but being open-source, it 
allows Java developers to get some concrete Lisp, if they choose to 
study O/R-mapping tools for discovering the strenghts of CL).

Of course if you put enought functionality in your project, that would 
serve not only Java developers, but also some CL users :)

...
...

One of the posters mentioned one of the Paepcke's papers. There are also 
his papers about PCLOS - an O/R mapping framework. But for real code, 
you will need to use current MOP documentation.  There is also a recent 
paper by Arthur Lee and Joseph Zachary called "Adding Support for 
Persistence to CLOS via Its Metaobject Protocol". There is also an old 
paper by Theodore Phelps, called "Persistent object storage in 
collaborative systems".

Some posters mentioned cl-prevalence. Escaping the context of O/R 
mapping tools, and entering the one of the Main Memory Databases 
(prevalence is such, and besides of the marketing of the original 
prevalence project, it is either the first nor best one in history, but 
may be the simplest to implement in Java), I think that the concepts 
found in projects like HiBase and Monet (there is even a similar and 
really good commercial product calles KDB from K Systems, which seem to 
predate Monet, but Monet is better documented) are more intersting in 
terms of the "Right Way". But both would require a deep understanding of 
your CL implementation and/or support from your vendor.

In the context of pure Lisp OODBs there is (besides PLOB) an old paper 
from by and Swanson called "UCL+P - Defining and Implementing Persistent 
Common Lisp".

I suppose, that enhancing cl-prevalence, implementing a better MMDB or 
replacing the backend of PLOB with something accessible, would also be a 
great contribution to both communities :)

With best regards
Plamen
--
Today is the first day of the rest of your life.
From: Will Hartung
Subject: Re: CLOS and databases
Date: 
Message-ID: <c3nt9j$2a6pj1$1@ID-197644.news.uni-berlin.de>
"Plamen Stamov" <··@stamov.ch> wrote in message
·············@news01.datazug.ch...

> Hello,
>
> I would not like to discourage you in your enterprise, but I think that
> to "really knock the socks off the Java people", you will have to
> implement something more difficult than that.
>
> Current O/R mapping products (not only commercial ones) include more or
> less the following functionality :

Sure, but you don't necessarily need that to "knock the socks off".

All of these tools are external to Java. Using either XML or augmenting
JavaDoc comments.

What Erann is doing is "simply" extending the object system in CL to support
a "crude persistence".

General purpose OO/Relational mapping packages are complicated, because the
task is complicated.

But within some contraints, simple class mapping isn't overly arduous. If
you can live with Class == Table, you can go quite a long way.

Implement it elegantly as a combination of macros, GFs and objects, on top
of what CL already provides, and it makes for a nice showcase of the system.

Many will poo-poo it because it doesn't do a, b, c, or d. And what they will
overlook is that when it's all done, you have basic persistence in CL.

When you add code to a CL image, you get CL. With Java, you get Java, Ant,
Hibernate, XML, XDoclet, etc. etc. etc. A bunch of disparate tools.

It is a wonder that they integrate as well as they do, but in the end, it's
a bunch of seperate entities, preprocessors, postprocessors, classloaders,
etc.

Whether in the end any socks will be knocked akimbo, is another matter.

Regards,

Will Hartung
(·····@msoft.com)
From: Erann Gat
Subject: Re: CLOS and databases
Date: 
Message-ID: <gNOSPAMat-2203041605260001@k-137-79-50-101.jpl.nasa.gov>
In article <···············@ID-197644.news.uni-berlin.de>, "Will Hartung"
<·····@msoft.com> wrote:

> Implement it elegantly as a combination of macros, GFs and objects, on top
> of what CL already provides, and it makes for a nice showcase of the system.
> 
> Many will poo-poo it because it doesn't do a, b, c, or d. And what they will
> overlook is that when it's all done, you have basic persistence in CL.

With no need to read a book to learn how to use it.  For a few hundred LOC
(hopefully).

That's the thing that most people don't seem to get: it's not about what
you can and can't do, it's about how much effort it takes to do it.

"Can you do X using Y?" is the wrong question.  The right question is:
"How much work is it to do X using Y compared to doing X using Z?  (And
part of the tally of work required has to unclude the time it takes to
read the manual.)


> Whether in the end any socks will be knocked akimbo, is another matter.

I regret ever having used that phrase.

E.
From: plamen
Subject: Re: CLOS and databases
Date: 
Message-ID: <c10ab1d8.0403231007.136ad59d@posting.google.com>
me :
>How easy it is to implement a simple O/R mapping library is allready 
>demonstrated by UnCommonSQL and the like (I'm placing it before 
>CommonSQL not because of it's qualities, but being open-source, it 
>allows Java developers to get some concrete Lisp, if they choose to 
>study O/R-mapping tools for discovering the strenghts of CL).
...
>Of course if you put enought functionality in your project, that
would
>serve not only Java developers, but also some CL users :)

> In article <···············@ID-197644.news.uni-berlin.de>, "Will Hartung"
> <·····@msoft.com> wrote:
> 
> > Implement it elegantly as...

Yes.
 
> With no need to read a book to learn how to use it.  For a few hundred LOC
> (hopefully).
> 
> That's the thing that most people don't seem to get: it's not about what
> you can and can't do, it's about how much effort it takes to do it.
> 
> "Can you do X using Y?" is the wrong question.  The right question is:
> "How much work is it to do X using Y compared to doing X using Z?  (And
> part of the tally of work required has to unclude the time it takes to
> read the manual.)
> 

Yes. But again, it is allready done by projects like UnCommonSQL (In
the context of O/R mappers). They miss may be some PowerPoint slides
explaining what actually happens in the (for non-lisper)
non-documented source code (which consists of actually only four
bigger files!), because education isn't their main motive (and from
your post I got that you want at first place to USE your O/R-mapper).
So I could not see any added value to the existing materials, from
which a non-lisper may learn. How to do macros, GFs etc. is explained
more or less in a lot of books, and examples exist in much more open
source projects. That CL may cut the time to market is also known. And
that this is only one of several factors one may take in account for
evaluation of a technology for a concrete project is also known. And
to help CL providing a "success story" would be nice, but a very, very
simple O/R mapper would (in my view) not suffice.

Because I missed the added value in that respect, I completly ignored
it in my post and supposed that you want to add value in terms of
functionality and in the same time are not informed about the current
state of affaires in Java. So I wanted to help you better predict the
time you need to invest. Further I supposed that an O/R mapper which
is simpler than UnCommonSQL would be of less use...

I see I was wrong. 

My point was that it would be usefull for both communities to add
value to something. My second point was that it would be more usefull
for you if you use something more usefull than to build from scratch
something less usefull :)

I'm sorry that all that got smashed throught the virtuosity of my
english :)

Plamen
--
When CL is your hammer, does everybody look like a thumb?
From: Cameron MacKinnon
Subject: Re: CLOS and databases
Date: 
Message-ID: <QYudnbLWS4BDpcPdRVn-iQ@golden.net>
Erann Gat wrote:
> My goal here is not only to make something functional, but also to
> highlight the power of CLOS with something that will really knock the
> socks off the Java people, so I really want to do this the Right Way.

Well, we've heard from the Java camp about the state of the art there, 
so here's some thoughts:

By default, storable objects should map one class to a table, with all 
slots stored, and the class and slot names corresponding to the table 
and column names. Overriding this default mapping would be a "nice to have".

Instantiating an object should automatically retrieve it from the DB, if 
it exists.

Updating any slot ought to add that object to a queue of objects to be 
written. Once the queue reaches x objects, or every y seconds, or upon 
shutdown, the queue gets flushed to the database. This is a high 
performance, non-ACID strategy. Setting x=1 approximates ACID.

Alternatively, you could designate one slot as special, and setting that 
slot would cause the whole object to be queued for write. In this 
scheme, the programmer is responsible for updating slots in a partial 
order, and for always touching the special slot whenever any other slot 
is updated.

Done right, the number of keystrokes required for the user of storable 
ought to be very minimal.

Now, what happens if the class is redefined to add slots? The storable 
code notices that the class definition is out of sync with the database, 
and either
a) updates the database schema by adding or dropping a column (table 
create & copy may be required)
b) creates another table, and remembers that there are now n+1 versions 
of the table. From now on, object instantiations must check old versions 
of the table if the newest version fails to turn up a match. When a 
match is found in an older table, it is moved to the newer table 
(optionally).

Supporting this for the add/drop of a slot in one class is trivial. 
Support for moving a slot from one class to another if a 1:1 mapping 
between them exists ought not to be too difficult. Automatically 
supporting more advanced schema redesigns left as an exercise...

Being able to update the object schema and/or the class<->database 
mapping seamlessly while the application is running is a "knock your 
socks off" feature. People who insist that their development environment 
has moved beyond the waterfall model won't be able to follow you through 
THOSE rapids.

And finally, because every project needs a stupid acronym to gain 
mindshare, may I suggest SWIM -- "Store What I Mean"?

-- 
Cameron MacKinnon
Toronto, Canada
From: Erann Gat
Subject: Re: CLOS and databases
Date: 
Message-ID: <gNOSPAMat-2103041809350001@192.168.1.52>
In article <······················@golden.net>, Cameron MacKinnon
<··········@clearspot.net> wrote:

> Erann Gat wrote:
> > My goal here is not only to make something functional, but also to
> > highlight the power of CLOS with something that will really knock the
> > socks off the Java people, so I really want to do this the Right Way.
> 
> Well, we've heard from the Java camp about the state of the art there, 
> so here's some thoughts:
> 
> By default, storable objects should map one class to a table, with all 
> slots stored, and the class and slot names corresponding to the table 
> and column names. Overriding this default mapping would be a "nice to have".
> 
> Instantiating an object should automatically retrieve it from the DB, if 
> it exists.
> 
> Updating any slot ought to add that object to a queue of objects to be 
> written. Once the queue reaches x objects, or every y seconds, or upon 
> shutdown, the queue gets flushed to the database. This is a high 
> performance, non-ACID strategy. Setting x=1 approximates ACID.
> 
> Alternatively, you could designate one slot as special, and setting that 
> slot would cause the whole object to be queued for write. In this 
> scheme, the programmer is responsible for updating slots in a partial 
> order, and for always touching the special slot whenever any other slot 
> is updated.
> 
> Done right, the number of keystrokes required for the user of storable 
> ought to be very minimal.

Yep, that's pretty much what I'm up to.

> Now, what happens if the class is redefined to add slots?

Yes, a most interesting question :-)

> The storable 
> code notices that the class definition is out of sync with the database,

Or you can shadow defclass so it doesn't have to "notice".
 
> and either
> a) updates the database schema by adding or dropping a column (table 
> create & copy may be required)

MySQL has a handy-dandy "alter table" command :-)


> Supporting this for the add/drop of a slot in one class is trivial. 
> Support for moving a slot from one class to another if a 1:1 mapping 
> between them exists ought not to be too difficult.

I'm not sure what you mean by "moving a slot from one class to another."

> Being able to update the object schema and/or the class<->database 
> mapping seamlessly while the application is running is a "knock your 
> socks off" feature. People who insist that their development environment 
> has moved beyond the waterfall model won't be able to follow you through 
> THOSE rapids.

OK, you've got me fired up now :-)

> And finally, because every project needs a stupid acronym to gain 
> mindshare, may I suggest SWIM -- "Store What I Mean"?

An interesting suggestion.  I'll take it under advisement.

Thanks for the cogent and constructive feedback.

E.
From: Cameron MacKinnon
Subject: Re: CLOS and databases
Date: 
Message-ID: <Gfednf3dXYWz4sPdRVn-vg@golden.net>
Erann Gat wrote:
>>Supporting this for the add/drop of a slot in one class is trivial. 
>>Support for moving a slot from one class to another if a 1:1 mapping 
>>between them exists ought not to be too difficult.
> 
> 
> I'm not sure what you mean by "moving a slot from one class to another."

Say you've got two tables in the database, each with one row per 
employee. Classical database theory says this should all be in one 
table, but if one table is for employee ID, login and home directory, 
used all the time, and the other table has numbers only used every two 
weeks for running payroll, it can be a big win to split them, so the 
payroll stuff isn't taking up RAM all the time  as a consequence of the 
other info being constantly used.

Now someone decides that maybe a certain field should be moved from one 
table to the other. The DB administrator creates or alters the 
destination table, runs a select to move the field over, creates the new 
source table (now missing a column), runs a select to move the data 
over, drops the old tables, and builds indexes on and renames the new 
ones. Also, someone's got to go through the source of all the 
applications that use those tables, changing the SQL on all the insert, 
select and update statements that are affected. Huge pain in the ass, 
which is why database stuff is generally done waterfall model.

I think I came across the following articles last year sometime, and 
they just blew me away. A high pressure development environment, a 
database constantly in flux, and lots of legacy applications which 
continue to function, talking to what appears to be version (a few 
months and many changes ago) of the database. Lisp being the magic 
bullet, of course. It was never like this where I worked!

Tracking Assets in the Production of 'Final Fantasy : The Spirits Within'
http://www.lava.net/~shiro/Private/essay/gdc2002.html

Shooting A Moving Target--- An Experience In Developing A Production 
Tracking Database
http://www.shiro.dreamhost.com/scheme/docs/jlugm2000.html

-- 
Cameron MacKinnon
Toronto, Canada
From: David Steuber
Subject: Re: CLOS and databases
Date: 
Message-ID: <m2u10hnsbu.fsf@david-steuber.com>
Cameron MacKinnon <··········@clearspot.net> writes:

> I think I came across the following articles last year sometime, and
> they just blew me away. A high pressure development environment, a
> database constantly in flux, and lots of legacy applications which
> continue to function, talking to what appears to be version (a few
> months and many changes ago) of the database. Lisp being the magic
> bullet, of course. It was never like this where I worked!
> 
> Tracking Assets in the Production of 'Final Fantasy : The Spirits Within'
> http://www.lava.net/~shiro/Private/essay/gdc2002.html
> 
> Shooting A Moving Target--- An Experience In Developing A Production
> Tracking Database
> http://www.shiro.dreamhost.com/scheme/docs/jlugm2000.html

I read the Final Fantasy one from a link on the alu.cliki.net site.
Both those articles are reachable from there (same author).  Very
impressive stuff.

I worked in an environment using Perl + Perl::DBI + Oracle where a
tech lead managed to get the DB people (there was some serious
compartmentalization at the company) to do a 1:1 object to DB table
mapping.  There was a bit of a problem though with the approach.
Objects often contained references to other objects so that
instantiating them from the database ended up grabbing megabytes of
data.  It is possible to saturate gigabit ethernet.

That problem was fixed (?) by using a lazy loading algorithm so that
slots were loaded on demand and then cached.

The big problem I had with that particular architecture was that the
DB schema was fairly quickly cast into stone.  That wouldn't have
been a problem if it wasn't for the simple fact that the database was
driving a website.  The cost of displaying 1:1 mapped objects on web
pages was high.

I found myself creating a number of what I called pseudoclasses.  They
were so named because they did not exist in the database as such.
They were constructed from SELECT statements that were far more
efficient than aggregating a bunch of 'real' classes because only a
single query was required.  I was able to get away with them as they
were read only so synchronization was not an issue.  When I say 'get
away with them' I really mean that in a political sense rather than a
technical sense.

I'm sure that the defects of the particular implementation play a
large role in my opinion here, but I got the impression that while a
1:1 class mapping to tables in an RDBMS seems good on paper, it is
not really always the way to go.

I really do like that idea about having the database schema auto
updated when you change a class definition.  If it could track moving
a slot from one class to another, that would blow off more than just
socks I think.

-- 
Those who do not remember the history of Lisp are doomed to repeat it,
badly.

> (dwim x)
NIL