From: mdj on
On Jan 7, 11:12 pm, "Thomas F. Burdick" <tburd...(a)gmail.com> wrote:

> Yeah, that is a nice feature of ccl. Their original cocoa bridge was
> pretty ugly compared to what a couple of us sbcl users were
> developing, but theirs got nicer over time and ours got wiped out by
> changes to the objc runtime, so I guess they had the better
> strategy :-)

Shame there isn't two!

> > I must admit though, other than during development, I can't come up
> > with a good use-case for the more elaborate functionality you elude
> > to ...
>
> "Other than during development". Well, yeah, that's generally when you
> redefine classes/structs :-)
>
> In general, I greatly prefer my Lisp to either do the right thing or
> give me an error, not give me the wrong answer.

A good position to hold. I'm ambivalent about it to be honest in this
case, so I don't mind too much that the implementations seem to have
taken the easy road.
From: mdj on
On Jan 8, 12:29 am, Madhu <enom...(a)meer.net> wrote:
> * mdj <369f86a8-5b3f-47b3-83c1-93756be22...(a)r5g2000yqb.googlegroups.com> :
> Wrote on Thu, 7 Jan 2010 06:21:01 -0800 (PST):
>
> | On Jan 7, 11:50 pm, Madhu <enom...(a)meer.net> wrote:
> |
> |> Where did I "lapse into `Indian pigeon English'" ?  Can you provide a
> |> citation?
> |
> | On Jan 7, 3:32 pm, Madhu <enom...(a)meer.net> wrote:
> |
> |> Again you fell for the Ron's trick.  Last time it was on the meaning of
> |> "interesting". Now it is on the meaning of "Layout".
>
> And what is the flaw here?  maybe you can read "based on" for "on"

"the Ron's"
From: Pascal Costanza on
On 07/01/2010 10:15, mdj wrote:
> On Jan 7, 6:58 pm, "Thomas F. Burdick"<tburd...(a)gmail.com> wrote:
>> On Jan 7, 4:14 am, mdj<mdj....(a)gmail.com> wrote:
>>
>>
>>
>>> you (IMO incorrectly) stated that a structure #S(:a a :b b)
>>> which has it's definition altered to (b a) has *not* been re-organised
>>> when it later displays as #S(:b a :a b). If it was re-organised it
>>> would display as #S(:b b :a a), which it did not. There is, you'll
>>> agree, only two possible organisations for that structure. I'm sorry
>>> you seem to think this makes me a dishonest person, but it seems clear
>>> to me that no reasonable implementation would attempt to reorganise
>>> the (potentially terabytes) of existing instances when a defstruct is
>>> redefined. One has to check what their own implementation does, but I
>>> think you'll find that the one you're advocating is the *least*
>>> likely, considering it's only even possible at all if the structures
>>> remain the same size, and in that case it isn't even necessary to do
>>> it at all. I would contend that the only reason implementations allow
>>> redefinition at all is to facilitate prototyping and bottom-up design,
>>> since the results of doing so will in practice be unpredictable at
>>> best, contrived examples notwithstanding.
>>
>> There are other alternatives to either (1) blindly assuming the new
>> layout applies to the old instances, or (2) eagerly changing the
>> layout of existing instances. You could hypothetically update them
>> lazily using (something like) update-instance-for-redefined-class. I
>> don't know of any implementation that does that, however. SBCL/CMUCL
>> offer the option to mark the old instances as invalid, so, while you
>> won't get A when trying to access the A slot in the above example, at
>> least you'll get an error instead of B. I think it's too bad more
>> implementations don't do this, it's really useful behavior.
>
> I wasn't aware of that for SBCL (which I use primarily) but I've been
> dabbling a bit with Clozure so I'll check out what it offers next time
> I transfer some code to it (I was tempted by the MacOS X integration
> possibilities)
>
> I must admit though, other than during development, I can't come up
> with a good use-case for the more elaborate functionality you elude
> to ...

ContextL uses class redefinition internally for its implementation. It
doesn't need the whole update-instance-for-redefined-class protocol, but
it relies on a correct update of the instance layout.


Pascal

--
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
From: Madhu on
* mdj <4e7b1ccf-3154-4ffa-b855-a4ce05aaa647(a)22g2000yqr.googlegroups.com> :
Wrote on Thu, 7 Jan 2010 06:43:38 -0800 (PST):

| On Jan 8, 12:29 am, Madhu <enom...(a)meer.net> wrote:
|> * mdj <369f86a8-5b3f-47b3-83c1-93756be22...(a)r5g2000yqb.googlegroups.com> :
|> Wrote on Thu, 7 Jan 2010 06:21:01 -0800 (PST):
|>
|> | On Jan 7, 11:50 pm, Madhu <enom...(a)meer.net> wrote:
|> |
|> |> Where did I "lapse into `Indian pigeon English'" ?  Can you
|> |> provide a citation?
|> |
|> | On Jan 7, 3:32 pm, Madhu <enom...(a)meer.net> wrote:
|> |
|> |> Again you fell for the Ron's trick.  Last time it was on the
|> |> meaning of "interesting". Now it is on the meaning of "Layout".
|>
|> And what is the flaw here?  maybe you can read "based on" for "on"
|
| "the Ron's"

Indeed. Sorry, I should've capitilized the `The'

pls read: ``Again you fell for The Ron's trick.'

'
From: Ron Garret on
In article
<346e5c92-8d67-45cd-b93d-87fa1187e932(a)a32g2000yqm.googlegroups.com>,
"Thomas F. Burdick" <tburdick(a)gmail.com> wrote:

> On Jan 7, 10:21 am, Ron Garret <rNOSPA...(a)flownet.com> wrote:
> > In article
> > <6d821556-254b-4df1-87ce-746055a1f...(a)a15g2000yqm.googlegroups.com>,
> >  "Thomas F. Burdick" <tburd...(a)gmail.com> wrote:
> >
> >
> >
> >
> >
> > > On Jan 7, 4:14 am, mdj <mdj....(a)gmail.com> wrote:
> >
> > > > you (IMO incorrectly) stated that a structure #S(:a a :b b)
> > > > which has it's definition altered to (b a) has *not* been re-organised
> > > > when it later displays as #S(:b a :a b). If it was re-organised it
> > > > would display as #S(:b b :a a), which it did not. There is, you'll
> > > > agree, only two possible organisations for that structure. I'm sorry
> > > > you seem to think this makes me a dishonest person, but it seems clear
> > > > to me that no reasonable implementation would attempt to reorganise
> > > > the (potentially terabytes) of existing instances when a defstruct is
> > > > redefined. One has to check what their own implementation does, but I
> > > > think you'll find that the one you're advocating is the *least*
> > > > likely, considering it's only even possible at all if the structures
> > > > remain the same size, and in that case it isn't even necessary to do
> > > > it at all. I would contend that the only reason implementations allow
> > > > redefinition at all is to facilitate prototyping and bottom-up design,
> > > > since the results of doing so will in practice be unpredictable at
> > > > best, contrived examples notwithstanding.
> >
> > > There are other alternatives to either (1) blindly assuming the new
> > > layout applies to the old instances, or (2) eagerly changing the
> > > layout of existing instances. You could hypothetically update them
> > > lazily using (something like) update-instance-for-redefined-class. I
> > > don't know of any implementation that does that, however. SBCL/CMUCL
> > > offer the option to mark the old instances as invalid, so, while you
> > > won't get A when trying to access the A slot in the above example, at
> > > least you'll get an error instead of B. I think it's too bad more
> > > implementations don't do this, it's really useful behavior.
> >
> > Marking all the old instances as invalid can still be expensive if there
> > are a lot of them.  A better approach would be to have all the instances
> > have a back-pointer to a (shared) wrapper, and have the wrapper marked
> > as invalid when the struct is redefined.
>
> That's how it's actually implemented.
>
> > Whether this is a good idea or not depends on whether you think that
> > DEFSTRUCT ought to be a high-level facility or a low-level one.
>
> Not sure I know what you mean here. If you mean that you think
> the :layout vector behavior could be seen as the model, and structure-
> instances would be expected to follow that .... it seems weird (and I
> would disagree about that being the best behavior), but I guess I
> could see that. But if you would take that interpretation, and would
> think that foo-a should return either A or B, then at least in the
> situation:
>
> (defstruct foo a b)
> (setq >>foo (make-foo :a 'a :b 'b))
> (defstruct foo a b c)
> (foo-c >>foo)
>
> you should want the call to foo-c to raise an error, and not give you
> the content of the memory word one past >>foo, right?

Certainly. But that's a very different kind of example.

Lisp has always had a bit of an identity crisis with respect to the
level of abstraction at which it operates. On the one hand, it
*completely* abstracts away the underlying Von Neumann machine,
replacing it with cons cells, vectors, arrays, characters, strings, hash
tables etc. as fundamental data structures. So the concept of "the
memory word one past >>foo" does not even exist in Lisp. The closest
you can come to this concept is "the element of the sequence whose index
is the length of the sequence", which of course by definition does not
exist. So relative to C, Lisp is a high-level language.

On the other hand, Lisp has a strong cultural bias against creating
*new* abstractions, preferring instead to pun mainly on cons cells.
There is no such thing, for example, as an abstract associative map in
Lisp. There is not even a cultural convention for such a thing.
Instead, people use ALists, PLists, and occasionally (as an advanced
topic) hash tables. This is woven deeply into the fabric of Lisp
culture and pedagogy, to the point where people sometimes think (even if
only briefly) that ALISTS and PLISTS are an exhaustive enumeration of
all the possible implementations of an associative map.

ALists and PLists are associate maps in exactly the same sense that C
strings are strings. C strings aren't "really" strings, they are
pointers, and to behave like strings they rely on the programmer to
adhere to certain conventions, like marking the end of the string with a
null character. If the programmer fails to adhere to those conventions,
bad things happen. ALists and PLists analogously are not really
associative maps, they are cons cells. To behave like associative maps
they rely on the programmer to adhere to certain conventions, and if the
programmer fails to adhere to those conventions bad things happen. Even
lists aren't really lists, they are cons cells. If you call TYPE-OF on
a list the result is not LIST, it is CONS. They rely on the programmer
adhering to certain conventions in order to act like lists, or bad
things happen. Determining whether a given cons cell is a (valid) list
or alist or plist or none of the above is a non-trivial exercise.

In this sense, lisp is "low level" with respect to a certain
non-extensible set of primitives. It is a much richer set than the set
that C is built on, but it is nonetheless non-extensible. One can
consider ALists and PLists to be "low level" with respect to that set of
primitives.

DEFSTRUCT is different. You can use DEFSTRUCT to actually define new
type, e.g.:

? (defstruct foo x y)
FOO
? (make-foo)
#S(FOO :X NIL :Y NIL)
? (type-of *)
FOO

DEFSTRUCT and DEFCLASS are the *only* two constructs in CL that let you
do this, by the way. DEFTYPE, notwithstanding its name, does not define
new types, it merely defines synonyms for subsets, intersections, and
unions of existing types.

The types defined by DEFSTRUCT act an awful lot like associative maps,
and so it is tempting to think of them as if they *were* associative
maps (which is the reason Matt fell into the trap of thinking there must
be alists or plists lurking underneath). And that is a perfectly valid
way of thinking about them. That's the "high-level" point of view. On
this view, one would expect:

? (defstruct foo x y)
FOO
? (setf foo1 (make-foo :x 1 :y 2))
#S(FOO :X 1 :Y 2)
? (defstruct foo y x)
FOO
? (foo-x foo1)

to return 1.

But there is another way of thinking about the types defined by
DEFSTRUCT, and that is not as an associative map, but rather a set of
symbolic labels layered on top of a SEQUENCE (which is also not a real
type in CL, but rather just the union of lists and vectors). DEFSTRUCT
explicitly supports with view with its TYPE option. When you define a
new structure type with a TYPE argument, you *force* DEFSTRUCT to behave
in this low-level way. It is therefore not unreasonable to suppose that
the designers intention was that thinking about structures defined by
defstruct as associative maps is simply wrong, that defstruct is
unambiguously a low-level construct (notwithstanding its flirtation with
the high-level concept of defining new types), and that the above
example should be expected to return 2.

The reason that (foo-c >>foo) returns an error has nothing to do with
any of this, it has to do with the fact that length-checking of
sequences is built in to Lisp's fundamental low-level data model. It
has nothing do with which view of DEFSTRUCT one chooses to subscribe to.

rg