From: mdj on 7 Jan 2010 08:54 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 7 Jan 2010 09:43 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 7 Jan 2010 10:10 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 7 Jan 2010 12:18 * 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 7 Jan 2010 13:40
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 |