From: David Fisher
Subject: dependencies!
Date: 
Message-ID: <14030ca9.0403200723.52b3a017@posting.google.com>
Let's say you are working on a big program interactively, and you have
these fragments in it:

(defstruct a (x 1))

(defvar a 3)

(defun foo (x) (a-x x))

Now, remember, this is a big program with hundreds of thousands of
definitions that depend on each other.

You want to change A struct to

(defstruct a (x 1) (y 2))

Problem 1: you can't do it without first uninterning A.
Problem 2: how to find and "refresh" all those FOOs that depend on the
representation of struct A? (and at least in my implementation, you
need to)

From: Brian Downing
Subject: Re: dependencies!
Date: 
Message-ID: <kxZ6c.48445$KO3.156867@attbi_s02>
In article <····························@posting.google.com>,
David Fisher <·············@yahoo.com> wrote:
> You want to change A struct to
> 
> (defstruct a (x 1) (y 2))
> 
> Problem 1: you can't do it without first uninterning A.
> Problem 2: how to find and "refresh" all those FOOs that depend on the
> representation of struct A? (and at least in my implementation, you
> need to)

Use DEFCLASS instead of DEFSTRUCT.  See
UPDATE-INSTANCE-FOR-REDEFINED-CLASS for how CLOS solves your
"refreshing" problem.

http://www.lispworks.com/reference/HyperSpec/Body/f_upda_1.htm

-bcd
-- 
*** Brian Downing <bdowning at lavos dot net> 
From: David Fisher
Subject: Re: dependencies!
Date: 
Message-ID: <14030ca9.0403201214.74dea0cc@posting.google.com>
Brian Downing <·············@lavos.net> wrote in message news:<······················@attbi_s02>...
> In article <····························@posting.google.com>,
> David Fisher <·············@yahoo.com> wrote:
> > You want to change A struct to
> > 
> > (defstruct a (x 1) (y 2))
> > 
> > Problem 1: you can't do it without first uninterning A.
> > Problem 2: how to find and "refresh" all those FOOs that depend on the
> > representation of struct A? (and at least in my implementation, you
> > need to)
> 
> Use DEFCLASS instead of DEFSTRUCT.  See
> UPDATE-INSTANCE-FOR-REDEFINED-CLASS for how CLOS solves your
> "refreshing" problem.
> 
> http://www.lispworks.com/reference/HyperSpec/Body/f_upda_1.htm

Thanks, but no thanks ;-)

Real hackers do not use CLAWS, or any of the 1980-90s hype. C++ made
the mistake of conflating very different concepts: modularity,
abstraction, inheritance and polymorphism. The same is happening here:
I asked for dependency analysis, which has nothing to do with "OO",
and you are suggesting I use CLAWS. (This doesn't mean I fail to
appreciate your attempt to help though, so, as I said, thanks, but no
thanks).

As long as there is a breath in my body and a battery in my laptop, I
shall not use CLAWS (Or until I change my mind)
From: ·········@random-state.net
Subject: Re: dependencies!
Date: 
Message-ID: <c3icen$5edc3$1@midnight.cs.hut.fi>
David Fisher <·············@yahoo.com> wrote:

> I asked for dependency analysis, which has nothing to do with "OO",
> and you are suggesting I use CLAWS. (This doesn't mean I fail to

Please, even though you were told to use defclass instead of
defstruct, I don't think the O-word was mentioned... ;-)

Defclass is not any more or less "OO" than defstruct -- you can
use specialize methods on both equally well, and class-of and
type-of &co deal with both. Despite what Java people may think,
just having classes does not OO make.

The fact is that what you want *is* catered for by CL, and the
suggested way is the natural way to do it. If you wish for the
convenience of defstruct but with classes, just write a macro
that gives you the accessors, type-predicate, copier, and
constructor with struct-style nmes.

> As long as there is a breath in my body and a battery in my
> laptop, I shall not use CLAWS (Or until I change my mind)

The very, very neat thing about CL is the way it slowly grows on
you.

You start by understanding that "Every paren 's good, every paren
's needed...", then learn basic idoms and features, and before
you notice it, you're programming in lisp. Eventually you hit a
hard place, and need to look for a way to deal with it. More
often than not what you want is covered by the spec. It's here
that your measure is taken -- do you:

 a) Learn and use the tools provided.

 b) Hold on to your preconceptions and try to drive nails with a
    screwdriver.

Once you have learned the tools and *then* have reasoned
complaints about them, *then* you can wave your hands and build a
better mousetrap. Not before: complaining about X being Y without
actually knowing X is just silly. Even arguments to authority
have more to them -- if you avoid certain parts of CL because
Someone With A Name doesn't like them, just say so.

It's still silly, but somewhat less so.

Here's hoping your battery runs out ;-)

Cheers,

  -- Nikodemus
From: Barry Wilkes
Subject: Re: dependencies!
Date: 
Message-ID: <4qsjjdpb.fsf@acm.org>
·············@yahoo.com (David Fisher) writes:

>
> Thanks, but no thanks ;-)
>
> Real hackers do not use CLAWS, or any of the 1980-90s hype. C++ made
> the mistake of conflating very different concepts: modularity,
> abstraction, inheritance and polymorphism. The same is happening here:
> I asked for dependency analysis, which has nothing to do with "OO",
> and you are suggesting I use CLAWS. (This doesn't mean I fail to
> appreciate your attempt to help though, so, as I said, thanks, but no
> thanks).
>
> As long as there is a breath in my body and a battery in my laptop, I
> shall not use CLAWS (Or until I change my mind)

OK, I give up.  What is/are CLAWS?

Barry.
From: Kenny Tilton
Subject: Re: dependencies!
Date: 
Message-ID: <Tb57c.3159$DV6.868@twister.nyc.rr.com>
Barry Wilkes wrote:

> ·············@yahoo.com (David Fisher) writes:
> 
> 
>>Thanks, but no thanks ;-)
>>
>>Real hackers do not use CLAWS, or any of the 1980-90s hype. C++ made
>>the mistake of conflating very different concepts: modularity,
>>abstraction, inheritance and polymorphism. The same is happening here:
>>I asked for dependency analysis, which has nothing to do with "OO",
>>and you are suggesting I use CLAWS. (This doesn't mean I fail to
>>appreciate your attempt to help though, so, as I said, thanks, but no
>>thanks).
>>
>>As long as there is a breath in my body and a battery in my laptop, I
>>shall not use CLAWS (Or until I change my mind)
> 
> 
> OK, I give up.  What is/are CLAWS?

Google says it is one of the pronunciations of CLOS, or:

    http://www.comp.lancs.ac.uk/ucrel/claws/

I am thinking the former. :)

kenneth

-- 
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: dependencies!
Date: 
Message-ID: <405D6BCC.B8C45826@setf.de>
David Fisher wrote:
> 
> Brian Downing <·············@lavos.net> wrote in message news:<······················@attbi_s02>...
> > In article <····························@posting.google.com>,
> > David Fisher <·············@yahoo.com> wrote:
> > > You want to change A struct to
> > >
> > > (defstruct a (x 1) (y 2))
> > >
> > > Problem 1: you can't do it without first uninterning A.
> > > Problem 2: how to find and "refresh" all those FOOs that depend on the
> > > representation of struct A? (and at least in my implementation, you
> > > need to)
> >
> > Use DEFCLASS instead of DEFSTRUCT.  See
> > UPDATE-INSTANCE-FOR-REDEFINED-CLASS for how CLOS solves your
> > "refreshing" problem.
> >
> > http://www.lispworks.com/reference/HyperSpec/Body/f_upda_1.htm
> 
> Thanks, but no thanks ;-)
> 
> Real hackers do not use CLAWS, or any of the 1980-90s hype. C++ made
> the mistake of conflating very different concepts: modularity,
> abstraction, inheritance and polymorphism. The same is happening here:
> I asked for dependency analysis, which has nothing to do with "OO",
> and you are suggesting I use CLAWS. (This doesn't mean I fail to
> appreciate your attempt to help though, so, as I said, thanks, but no
> thanks).
> 
> As long as there is a breath in my body and a battery in my laptop, I
> shall not use CLAWS (Or until I change my mind)

something does not add up here.

one proposes a use case which justifies automated dependent maintenance.
it is suggested that one use elements of the dependent maintenance protocol
which is standard to the language and which is intended to manage exactly the
kind of transformation which is described in the use case.
one avers, that one does not use clos, but does not specify why. (allegations
of inappropriate conflation of orthogonal concerns in other languages notwithstanding.)
one asserts, that a structure-based implementation is to be preferred, but one
neither says why nor gives even the slightest hint as to how one would go
about it.

please, do implement it. there are enough open-source clos implementations,
there are open source dylan implementations, and there are enough standard
hooks in lisp that it should be possible to implement a portable dependent
maintenance protocol for structures. this reader is curious how much of clos
one will have to reimplement and how much of the optimization advantage of
structures will remain.

...
From: David Fisher
Subject: Re: dependencies!
Date: 
Message-ID: <14030ca9.0403210827.1ad7869b@posting.google.com>
james anderson <··············@setf.de> wrote in message news:<·················@setf.de>...
> David Fisher wrote:
> > 
> > Brian Downing <·············@lavos.net> wrote in message news:<······················@attbi_s02>...
> > > In article <····························@posting.google.com>,
> > > David Fisher <·············@yahoo.com> wrote:
> > > > You want to change A struct to
> > > >
> > > > (defstruct a (x 1) (y 2))
> > > >
> > > > Problem 1: you can't do it without first uninterning A.
> > > > Problem 2: how to find and "refresh" all those FOOs that depend on the
> > > > representation of struct A? (and at least in my implementation, you
> > > > need to)
> > >
> > > Use DEFCLASS instead of DEFSTRUCT.  See
> > > UPDATE-INSTANCE-FOR-REDEFINED-CLASS for how CLOS solves your
> > > "refreshing" problem.
> > >
> > > http://www.lispworks.com/reference/HyperSpec/Body/f_upda_1.htm
> > 
> > Thanks, but no thanks ;-)
> > 
> > Real hackers do not use CLAWS, or any of the 1980-90s hype. C++ made
> > the mistake of conflating very different concepts: modularity,
> > abstraction, inheritance and polymorphism. The same is happening here:
> > I asked for dependency analysis, which has nothing to do with "OO",
> > and you are suggesting I use CLAWS. (This doesn't mean I fail to
> > appreciate your attempt to help though, so, as I said, thanks, but no
> > thanks).
> > 
> > As long as there is a breath in my body and a battery in my laptop, I
> > shall not use CLAWS (Or until I change my mind)
> 
> something does not add up here.
> 
> one proposes a use case which justifies automated dependent maintenance.
> it is suggested that one use elements of the dependent maintenance protocol
> which is standard to the language and which is intended to manage exactly the
> kind of transformation which is described in the use case.
> one avers, that one does not use clos, but does not specify why. (allegations
> of inappropriate conflation of orthogonal concerns in other languages notwithstanding.)
> one asserts, that a structure-based implementation is to be preferred, but one
> neither says why nor gives even the slightest hint as to how one would go
> about it.
> 
> please, do implement it. there are enough open-source clos implementations,
> there are open source dylan implementations, and there are enough standard
> hooks in lisp that it should be possible to implement a portable dependent
> maintenance protocol for structures. this reader is curious how much of clos
> one will have to reimplement and how much of the optimization advantage of
> structures will remain.
> 
> ...

Dependency analysis is a 100% compile-time issue. Give me a
code-walker that detects immediate dependencies in definitions (and
lambdas), and I'll write the tool you are talking about in just a few
lines (dependent definitions are refreshed). No run-time performance
penalty (unlike CLAWS)


As I wrote earlier, that's the problem with most OO systems: too many
orthogonal "features" are conflated - you want one feature (dependency
analysis) - OK, have a lot of things you didn't want with it, and give
up some things you had (performance, automatic accessors, etc.). CLAWS
cause brain rot. Thanks, but no thanks.
From: Brian Downing
Subject: Re: dependencies!
Date: 
Message-ID: <vZl7c.54829$KO3.189550@attbi_s02>
In article <····························@posting.google.com>,
David Fisher <·············@yahoo.com> wrote:
> Dependency analysis is a 100% compile-time issue. Give me a
> code-walker that detects immediate dependencies in definitions (and
> lambdas), and I'll write the tool you are talking about in just a few
> lines (dependent definitions are refreshed). No run-time performance
> penalty (unlike CLAWS)
> 
> As I wrote earlier, that's the problem with most OO systems: too many
> orthogonal "features" are conflated - you want one feature (dependency
> analysis) - OK, have a lot of things you didn't want with it, and give
> up some things you had (performance, automatic accessors, etc.). CLAWS
> cause brain rot. Thanks, but no thanks.

I admit you could do what you're talking about and reinvent this
particular wheel, but I have to wonder if you had dropped the anti-CLOS
ideology, written DEFCLASS-WITH-AUTOMATIC-ACCESSORS, gotten on with
developing your program, then profiled and replaced the DEFCLASSes with
DEFSTRUCTs /where they mattered/, you'd be done by now?

The tool already exists and you're kicking and screaming to avoid using
it.

Also, have you considered the possibility that using DEFCLASS instead of
your (currently nonexistent) automatic DEFSTRUCT dependency tracker
might actually make your development /faster/, since you won't be
waiting for big chunks of your program to recompile every time you
redefine a structure?

-bcd
-- 
*** Brian Downing <bdowning at lavos dot net> 
From: Helmut Eller
Subject: Re: dependencies!
Date: 
Message-ID: <m27jxegftu.fsf@62.178.77.205>
·············@yahoo.com (David Fisher) writes:

> Dependency analysis is a 100% compile-time issue. Give me a
> code-walker that detects immediate dependencies in definitions (and
> lambdas), and I'll write the tool you are talking about in just a few
> lines (dependent definitions are refreshed). No run-time performance
> penalty (unlike CLAWS)

What are the dependencies in the following program?  Given a
code-walker, how do you compute them?

(defun foo (x y) (setf (symbol-function x) y))
(foo 'bar (lambda () (baz)))
(foo 'baz (lambda () (bar)))
From: David Steuber
Subject: Re: dependencies!
Date: 
Message-ID: <m2d675q1ne.fsf@david-steuber.com>
Helmut Eller <········@stud3.tuwien.ac.at> writes:

> ·············@yahoo.com (David Fisher) writes:
> 
> > Dependency analysis is a 100% compile-time issue. Give me a
> > code-walker that detects immediate dependencies in definitions (and
> > lambdas), and I'll write the tool you are talking about in just a few
> > lines (dependent definitions are refreshed). No run-time performance
> > penalty (unlike CLAWS)
> 
> What are the dependencies in the following program?  Given a
> code-walker, how do you compute them?
> 
> (defun foo (x y) (setf (symbol-function x) y))
> (foo 'bar (lambda () (baz)))
> (foo 'baz (lambda () (bar)))

Interesting case there.

I may be wrong.  It's been known to happen inspite of all my attempts
to cover up the evidence.  But perhaps David Fisher has gone and
solved the halting problem (and the more general case who's name I
forget right now) much to the chagrin of mathematicians all over the
world.

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

> (dwim x)
NIL
From: james anderson
Subject: Re: dependencies!
Date: 
Message-ID: <405DE0CC.69D9AC9F@setf.de>
David Fisher wrote:
> 
> ...
> 
> Dependency analysis is a 100% compile-time issue. Give me a
> code-walker

http://www.cliki.net/admin/search?words=code+walker

>   that detects immediate dependencies in definitions (and
> lambdas), and I'll write the tool you are talking about in just a few
> lines (dependent definitions are refreshed). No run-time performance
> penalty (unlike CLAWS)

please. do. it could be useful.

...
From: Frode Vatvedt Fjeld
Subject: Re: dependencies!
Date: 
Message-ID: <2hisgy6kbk.fsf@vserver.cs.uit.no>
·············@yahoo.com (David Fisher) writes:

> Dependency analysis is a 100% compile-time issue. Give me a
> code-walker that detects immediate dependencies in definitions (and
> lambdas), and I'll write the tool you are talking about in just a
> few lines (dependent definitions are refreshed). No run-time
> performance penalty (unlike CLAWS)

CLOS is not the answer to dependency tracking, it's the answer to how
you do user-specified types in a dynamic and interactive programming
environment.

> As I wrote earlier, that's the problem with most OO systems: too many
> orthogonal "features" are conflated - you want one feature (dependency
> analysis) - OK, have a lot of things you didn't want with it, and give
> up some things you had (performance, automatic accessors, etc.). CLAWS
> cause brain rot. Thanks, but no thanks.

This has nothing to do with "OO systems" and your IMHO competely bogus
conception of CLOS as a conflation of separate issues. Common Lisp is
a dynamic and interactive programming environment. Defstruct and
structure-objects simply do not fit into this paradigm very well. CLOS
standard-objects do. The notion of tracking dependencies by way of
code-walking etc. is also completely counter to the essence of dynamic
and interactive programming.

Btw. much of the same can be said of macros, whose associated problems
of dependencies I consider one of the small conceptual warts of Common
Lisp. But in this case the great value of macros is obvious, and no
viable alternatives to their current incarnation exist. The value of
defstruct is merely a slight potential performance gain, other than
minor syntactical issues.

-- 
Frode Vatvedt Fjeld
From: Frode Vatvedt Fjeld
Subject: Re: dependencies!
Date: 
Message-ID: <2h4qsh6wxk.fsf@vserver.cs.uit.no>
Frode Vatvedt Fjeld <······@cs.uit.no> writes:

> Btw. much of the same can be said of macros, whose associated
> problems of dependencies I consider one of the small conceptual
> warts of Common Lisp. But in this case the great value of macros is
> obvious, and no viable alternatives to their current incarnation
> exist. The value of defstruct is merely a slight potential
> performance gain, other than minor syntactical issues.

Thinking about this a bit further, I think it's interesting to note
that macro dependencies only comes into play with compiled code; it's
not an issue so long as you keep your code uncompiled. There have been
some voices here on cll that we need (it would be nice to have)
"sealed classes" integrated with CLOS. There's a nice duality here
between the hypothetical sealed classes (that I gather would be
somewhat like structure-objects, only more cleverly done and better
integrated with CLOS) and the "sealed functions" we already have, that
are compiled-functions.

This suggests to me that if one was to develop some form of CLOS
sealing, with this there should also be developed a decent dependency
tracking system (implementation-independent? MOP-like?) that is also
able to cover macro dependencies, and perhaps other kinds of sealing
(function inlining comes to mind), in a manner that integrates well
(i.e.  as good as possible) with the dynamic paradigm. The overall net
effect would be to make it easier for programmers to make the
performance-vs-dynamicity trade-off. I suppose there might be
something to learn from Dylan in this area.

-- 
Frode Vatvedt Fjeld
From: David Fisher
Subject: Re: dependencies!
Date: 
Message-ID: <14030ca9.0403221149.7eda84a3@posting.google.com>
OK, I don't like CLAWS, CLAWS don't like me, and I don't like to
squander time talking about things that don't interest me much, but I
think this issue needs a closure (no pun intended), even though I
think I've been pretty clear while expressing my point in this thread.

* Helmut Eller wrote:

> What are the dependencies in the following program?  Given a
> code-walker, how do you compute them?
> 
> (defun foo (x y) (setf (symbol-function x) y))
> (foo 'bar (lambda () (baz)))
> (foo 'baz (lambda () (bar)))

You are making the right moves in the wrong direction. There are no
dependencies (for our purposes) here. Think of a better example (Hint:
must have macros or inline functions)

* David Steuber wrote:

> I may be wrong.  It's been known to happen inspite of all my attempts
> to cover up the evidence.  But perhaps David Fisher has gone and
> solved the halting problem (and the more general case who's name I
> forget right now) much to the chagrin of mathematicians all over the
> world.

I could prove the Halting Theorem (sic) if you woke me up in the
middle of the night. Your suggestion of my ignorance is not
appreciated.

HT has nothing to do with this.

* Frode Vatvedt Fjeld  wrote:

> Thinking about this a bit further, I think it's interesting to note 
> that macro dependencies only comes into play with compiled code; 
> it's not an issue so long as you keep your code uncompiled. 

Finally! Someone is beginning to get it. Reading the rest of your post
I think you aren't quite there yet though. Earlier post about macros
was insightful too.




The dependencies we are talking about here come from macro-expansion.
Macros only work at compile-time, so tracking these dependencies is a
100% compile-time issue, as I've been saying all along. QED.



* Tim Bradshow wrote:

> Bullshit.  

Ooooh, you must be smart!

> You have to find every reference to an instance of the 
> structure you're redefining and arrange for it to be nuked 
> or updated somehow.  That's not a statically determinable 
> property of the program in CL.

Same with class instances in CLAWS. (Hint: this is not what we mean by
dependency here. See above.)



Someone accused me of blindly following Paul Graham regarding OO.
Well, I think Paul Graham is a pretty smart guy, obviously, and worth
listening to. Listening to him is much better than following the OO
herds like sheep. Just because you value someone's opinion doesn't
mean you shouldn't internalize what they are saying and consider the
validity of their arguments.

In fact AFAICR my dislike of OO was only reaffirmed by Graham. But it
was inspired by a heretic (old non-Lisper hacker) I know who used C++
for a long while and began to really understand the problems with C++
OO. As he was telling me about them, it struck me that CLAWS is all
that and worse (no Lisp is not worse than C++, CLAWS to Lisp is worse
than OO is to C/C++).

To see the biggest problem with OO, one has to look at the definition
of the term first. I'd *like* to understand OO as "dynamic dispatch".
DD is useful and I don't have a particularly big problem with it. I
prefer not to build big class hierarchies though, and instead define
new languages that better express the problem at hand. One could ask,
if OO == "dynamic dispatch", why not just call it DD? That's right. OO
by *definition* is a conflation of pretty separate things: OO = A + B
+ C + D (where the values of A, B, C, D depend on the language). You
want B? Can't have it. Have A + C + D as well (but not for free!)

In conclusion: don't come at me with your CLAWS, unless I come out
first and say "I've been struck in the head by lightning, my IQ ain't
what it used to be, I like CLAWS now", or something to this effect.
Aside from that, any offerings of CLAWS by the present company will be
considered flamebait ;-)
From: Wade Humeniuk
Subject: Re: dependencies!
Date: 
Message-ID: <zXH7c.15$Ct5.9@edtnps89>
David Fisher wrote:

> In conclusion: don't come at me with your CLAWS, unless I come out
> first and say "I've been struck in the head by lightning, my IQ ain't
> what it used to be, I like CLAWS now", or something to this effect.
> Aside from that, any offerings of CLAWS by the present company will be
> considered flamebait ;-)

This is all very strange.  With LispWorks, structs are implemented with
CLOS as the metaclass structure-object.  I assume most other CLs do something
similar.  So you are using CLOS whether you like it or not.  Method
dispatch works on structures and classes equally.  Your denial of
reality is quite quaint, perhaps you should use a different
language.

Wade
From: Frode Vatvedt Fjeld
Subject: Re: dependencies!
Date: 
Message-ID: <2hr7vk63z3.fsf@vserver.cs.uit.no>
·············@yahoo.com (David Fisher) writes:

> [..] In conclusion: don't come at me with your CLAWS, unless I come
> out first and say "I've been struck in the head by lightning, my IQ
> ain't what it used to be, I like CLAWS now", or something to this
> effect.  Aside from that, any offerings of CLAWS by the present
> company will be considered flamebait ;-)

Well, I couldn't see any signs that you even begun to understand my
argument about dynamic and interactive programming environments and
how this relates to defclass vs. defstruct. I don't think you're able
to see CLOS for what it actually is behind your imaginary
"CLAWS". Please consider this bait for your IQ to come out from its
hiding if the scary claws should ever disappear, nothing else.

-- 
Frode Vatvedt Fjeld
From: Tim Bradshaw
Subject: Re: dependencies!
Date: 
Message-ID: <fbc0f5d1.0403220659.6861e2e2@posting.google.com>
d
> Dependency analysis is a 100% compile-time issue. 

Bullshit.  You have to find every reference to an instance of the
structure you're redefining and arrange for it to be nuked or updated
somehow.  That's not a statically determinable property of the program
in CL.
From: Gareth McCaughan
Subject: Re: dependencies!
Date: 
Message-ID: <87hdwg8mro.fsf@g.mccaughan.ntlworld.com>
Dave Fishes wrote:

>>> You want to change A struct to
>>> 
>>> (defstruct a (x 1) (y 2))
>>> 
>>> Problem 1: you can't do it without first uninterning A.
>>> Problem 2: how to find and "refresh" all those FOOs that depend on the
>>> representation of struct A? (and at least in my implementation, you
>>> need to)
>> 
>> Use DEFCLASS instead of DEFSTRUCT.  See
>> UPDATE-INSTANCE-FOR-REDEFINED-CLASS for how CLOS solves your
>> "refreshing" problem.
>> 
>> http://www.lispworks.com/reference/HyperSpec/Body/f_upda_1.htm
> 
> Thanks, but no thanks ;-)
> 
> Real hackers do not use CLAWS, or any of the 1980-90s hype. C++ made
> the mistake of conflating very different concepts: modularity,
> abstraction, inheritance and polymorphism. The same is happening here:
> I asked for dependency analysis, which has nothing to do with "OO",
> and you are suggesting I use CLAWS. (This doesn't mean I fail to
> appreciate your attempt to help though, so, as I said, thanks, but no
> thanks).

No one is telling you to use any of the "OO" features of DEFCLASS.

What you actually asked for was a way to define structure types
and be able to alter their definitions later on. Using DEFCLASS
is a solution to the problem you proposed. *Now* you've decided
that actually you weren't asking for a solution to that problem
but to a different problem: "How can I make dependency analysis
happen at compile time and use that to let me redefine structure
types?".

This problem statement sets alarm bells ringing in my head,
as problem statements of the form "How do I do X using Y?"
often do. Is there a real requirement (imposed by a customer,
or by a moral imperative, or something) that this be accomplished
using a compile-time dependency management system, or are the
real requirements things of the form "Accessing elements of
these structures must not take longer than ..."? If the latter,
where do the performance requirements come from, and have you
profiled the system using DEFCLASS to establish that doing it
that way isn't fast enough?

> As long as there is a breath in my body and a battery in my laptop,
> I shall not use CLAWS (Or until I change my mind)

Well, obviously one cannot argue with firmly entrenched
and jealously defended prejudice. I'm tremendously impressed,
by the way, that you thought of spelling it "CLAWS" to indicate
your dislike of it. It's also very cool to write "Micro$oft"
instead of "Microsoft" and "Winblows" instead of "Windows" --
you should try it. Or, according to taste, you could say "Linsux"
instead of "Linux". It's ever so clever.

                             *

In a later article:

> The dependencies we are talking about here come from macro-expansion.
> Macros only work at compile-time, so tracking these dependencies is a
> 100% compile-time issue, as I've been saying all along. QED.

So ... you define a struct called A with just one field,
called X. You run your program for a while, creating a lot
of As. Then you redefine A so that its instances now
have another field called Y, and your dependency analysis
system (whatever it is) finds everything that uses As and
does whatever's necessary to keep them working. So far,
so good. But presumably you're going to do something with
the Y field of your glorious new A structures ... so now
what are you going to do with all the As that are already
out there? If you leave them as they are, isn't your program
going to break as soon as one of them gets handed to a
function that assumes the new definition of A? If you don't
leave them as they are, then you have a *run-time* dependency
tracking issue, even if for some reason you don't like to
use the term "dependency" to describe it.

It happens that CLOS -- excuse me, CLAWS -- provides a
neat way to deal with this, but of course that's of no
interest to you because not defiling yourself with CLOS
is more important than writing the software.

Apropos this, your reply to Tim Bradshaw:

>> Bullshit.  
> 
> Ooooh, you must be smart!

Yes, as a matter of fact he is. I think calling something
"bullshit" is almost as clever as saying "CLAWS" instead of "CLOS",
though of course it isn't quite as clever.

>> You have to find every reference to an instance of the 
>> structure you're redefining and arrange for it to be nuked 
>> or updated somehow.  That's not a statically determinable 
>> property of the program in CL.
> 
> Same with class instances in CLAWS. (Hint: this is not what we mean by
> dependency here. See above.)

That would be "same with class instances" in the sense that
"class instances offer a way to do this automagically in a
single function call, whereas there is no way to do it for
struct instances without writing a big pile of code". And
whether you call this "dependency" or not, it's a real issue.

Maybe for some reason this issue doesn't apply to the system
you're building. Perhaps you have the "old" and "new" As
segregated somehow. But nothing you've said so far indicates
that, and it seems like you'd have to jump through a lot of
hoops to make it so.

> To see the biggest problem with OO, one has to look at the definition
> of the term first. I'd *like* to understand OO as "dynamic dispatch".
> DD is useful and I don't have a particularly big problem with it. I
> prefer not to build big class hierarchies though, and instead define
> new languages that better express the problem at hand. One could ask,
> if OO == "dynamic dispatch", why not just call it DD? That's right. OO
> by *definition* is a conflation of pretty separate things: OO = A + B
> + C + D (where the values of A, B, C, D depend on the language). You
> want B? Can't have it. Have A + C + D as well (but not for free!)

If you want a language where every feature can be eschewed
without paying any runtime efficiency cost for it, go use C++
where that was an explicit design principle. I happen to think
it was a bloody stupid design principle, because when you
design a language that way everyone has to pay a substantial
*implementation-time* cost on account of all the kludges you
have to make to preserve the "don't pay at runtime for what
you don't use" invariant, and of course that ends up costing
in runtime efficiency too because getting anything done is
so much more painful that programmers write worse code. But
if the principle is important to you, C++ is waiting for you,
and I promise you won't have to use CLOS there.

-- 
Gareth McCaughan
.sig under construc
From: ·········@random-state.net
Subject: Re: dependencies!
Date: 
Message-ID: <c3hp0n$59qqn$1@midnight.cs.hut.fi>
David Fisher <·············@yahoo.com> wrote:

> Problem 1: you can't do it without first uninterning A.
> Problem 2: how to find and "refresh" all those FOOs that depend on the
> representation of struct A? (and at least in my implementation, you
> need to)

Solution part 1: use defclass for everything that a) isn't utterly utterly
speed scritical b) is the least bit likely to have it's definition
changed.

Solution part 2: use a defsystem to manage the dependencies, so that
inlined accessors get the new the definitions. 

Solution part 3: if you really have a speed-critical thing that needs
to be a struct, and is going to keep changing around, and you are going
to have live instances around during developments, then arrange for the
constructor to store them in a weak hash-table so that you can update
them when needed. Alternatively, implement your own constructs on top
of vectors (or structs, for that matter) -- then you can design
the update logic to the exact requirements of your application, but I
doubt that would be worth the trouble.

Cheers,

  -- Nikodemus
From: james anderson
Subject: Re: dependencies!
Date: 
Message-ID: <405C6C8A.8290E02C@setf.de>
David Fisher wrote:
> 
> Let's say you are working on a big program interactively, and you have
> these fragments in it:
> 
somehow, it does not make sense that your "big program" has grown to "hundreds
of thousands of definitions", you've gotten to the point where you've
implemeted your data models with structures rather than clos objects, and yet
you feel it necessary to interactively resolve dependencies. but anyway, if
you are working on a "big program", and you really need to do this
interactively, you are likely using a development system which includes tools
to identify and offer access to references to variables, function, structures, etc.

in mcl, you open the definition in an editor, put the cursor on the symbol and
type control-c. it opens a list dialog with references to the symbol. acl and
lispworks do something similar.

if your development environment didn't come that way, and your program has
grown to hundreds of thousands of definitions, then somewhere along the way
you likely implememted this facility yourself. it tends to work by walking the
known function definitions and examining the called functions. this can get
complicated if you need to track macro references. that requires annotating
the function instances when they are compiled. for a look at how to approach
that, there was discussion on (i think) the cmucl mailing list some months back.

> (defstruct a (x 1))
> 
> (defvar a 3)
> 
> (defun foo (x) (a-x x))
> 
> Now, remember, this is a big program with hundreds of thousands of
> definitions that depend on each other.
> 
> You want to change A struct to
> 
> (defstruct a (x 1) (y 2))
> 
> Problem 1: you can't do it without first uninterning A.

why would need to unintern A?

> Problem 2: how to find and "refresh" all those FOOs that depend on the
> representation of struct A? (and at least in my implementation, you
> need to)

for the particular example, the redefinition likely has no effect on the
implementation of the a-x function as the structure layout is not likely to
have changed up to the position where x is stored. if you had instead cited

(defstruct a (y 2) (x 1))

then, for some structure implementations, the foo function would need to be
recompiled. there is still no need to unintern the symbol. not only is there
no need, it would likely have no effect on existing references as structure
references are often either open-coded or (compiler-)macro-expanded into
structure vector references with a constant offset. 

...
From: Kaz Kylheku
Subject: Re: dependencies!
Date: 
Message-ID: <cf333042.0403221622.5e41a56b@posting.google.com>
·············@yahoo.com (David Fisher) wrote in message news:<····························@posting.google.com>...
> Let's say you are working on a big program interactively, and you have
> these fragments in it:
> 
> (defstruct a (x 1))
> 
> (defvar a 3)
> 
> (defun foo (x) (a-x x))
> 
> Now, remember, this is a big program with hundreds of thousands of
> definitions that depend on each other.
> 
> You want to change A struct to
> 
> (defstruct a (x 1) (y 2))
> 
> Problem 1: you can't do it without first uninterning A.
> Problem 2: how to find and "refresh" all those FOOs that depend on the
> representation of struct A? (and at least in my implementation, you
> need to)

One thing you can do is stop the image and re-load your modules.

If you scrap the image and re-load (note that I did not say
re-compile) the modules of your program, then a new A-X will be
written. All the symbols will be re-interned from scratch.

FOO does not depend on the representation of A. It uses the abstract
accessor function A-X. You might be imagining a kind of rigid
dependency based on experience with how structures are treated in some
other languages. For instance in C, we might put the structure
definition into a header #include "x.h", and if that is touched, then
every translation unit which picks up that header has to be
recompiled. Translation units which construct instances of that struct
have to use the new definition so they generate an object of the
correct size, with all the latest struct members! Translation units
which use instances have to make sure they are compiled to the right
references, in case struct members were rearranged.

In Lisp, we are not forced to compile anything. And when we do, by
default the interfaces are flexible. A piece of compiled code code is
typically compatible with a new version of anything it interacts
with---and if it isn't, you can expect some kind of run-time error. So
there is a dependency on the *existence* of something, but not on its
specific version.

FOO will not work if it is given some object to which it cannot apply
A-X, or if A-X doesn't exist. If you change the struct so it has no
slot X, then it won't work. If you add slots and re-load everything,
FOO should work without being recompiled.

Suppose you have some compiled FOO which contains inlined, optimized
code representing (A-X X). Then you have potential problems with the
change of representation, if a new version of A has new slots before
X. If slots are just added after X, I'd expect things to work fine.

Inlined, compiled constructor calls (MAKE-A) will cause greater
problems if they make old versions of the struct objects that simply
don't have the new slots that are accessed by some new code.

I don't know whether any Lisps do this type of inlining out of the
box, and whether these issues show up in practice.

Without the inlining, A is effectively an abstract data type. Its
construction and manipulation is hidden behind the funcall interface.

Comments?
From: Thomas A. Russ
Subject: Re: dependencies!
Date: 
Message-ID: <ymioeqnryxg.fsf@sevak.isi.edu>
···@ashi.footprints.net (Kaz Kylheku) writes:

> 
> ·············@yahoo.com (David Fisher) wrote in message news:<····························@posting.google.com>...
> > Let's say you are working on a big program interactively, and you have
> > these fragments in it:
> > 
> > (defstruct a (x 1))
> > 
> > (defvar a 3)
> > 
> > (defun foo (x) (a-x x))
> ...
> One thing you can do is stop the image and re-load your modules.
> 
> If you scrap the image and re-load (note that I did not say
> re-compile) the modules of your program, then a new A-X will be
> written. All the symbols will be re-interned from scratch.
...
> FOO will not work if it is given some object to which it cannot apply
> A-X, or if A-X doesn't exist. If you change the struct so it has no
> slot X, then it won't work. If you add slots and re-load everything,
> FOO should work without being recompiled.

Actually, this is not true for most lisp implementations.
 
> Suppose you have some compiled FOO which contains inlined, optimized
> code representing (A-X X). Then you have potential problems with the
> change of representation, if a new version of A has new slots before
> X. If slots are just added after X, I'd expect things to work fine.

But since implementations are allowed to open code (a.k.a inline) the
structure references, you really do need to recompile the references in
order to get things to work properly.

So, as a practical matter, the rule is that all users of a DEFSTRUCT
need to be recompiled if the structure is changed.  There may be some
changes where this will not be necessary, but it is a safer bet to
follow the general rule if you want to have reliable code.


-- 
Thomas A. Russ,  USC/Information Sciences Institute