|
Prev: Lisp and Web Programming
Next: Koch figures
From: Joe Marshall on 17 Jul 2005 10:21 "Tron3k" <tron3k(a)gmail.com> writes: > Kent M Pitman wrote: >> Now think about >> (length '(a b . "foo")) > > Intriguing possibility: Is it necessarily the wrong thing for that to > return 5? Maybe it should do just that, while a more specific function > LIST-LENGTH would throw an error. Supposing you have a variable *FOO*. You call (length *foo*) => 5 Should (elt *foo* 4) give you an error? What should it return if *foo* is '(a b . "foo")? Could you SETF it? What should (length (concatenate 'list *foo* *foo*)) return? -- ~jrm
From: Kent M Pitman on 17 Jul 2005 10:55 "Tron3k" <tron3k(a)gmail.com> writes: > Kent M Pitman wrote: > > Now think about > > (length '(a b . "foo")) > > Intriguing possibility: Is it necessarily the wrong thing for that to > return 5? Maybe it should do just that, while a more specific function > LIST-LENGTH would throw an error. Necessarily? No. Likely? Yes. While you can think up uses for it, there are also already tons of non-uses (that is, errors wanting to be caught). Making those things "work" is the same as not detecting those errors. It's so easy to write an operator that does what you suggest you might in this case that one question is why you would want to perturb others' existing code by an incompatible definition ... But the main point is that whether this is right is a matter of "intention" and any assertion that this is something that is dynamically knowable is improper. As such, the decision is intrinsically arbitrary, and favoring compabitility in the arbitrary seems a good plan to me... See http://www.nhplace.com/kent/PS/EQUAL.html for more exposition on this.
From: Kent M Pitman on 17 Jul 2005 11:06 Joe Marshall <prunesquallor(a)comcast.net> writes: > "Tron3k" <tron3k(a)gmail.com> writes: > > > Kent M Pitman wrote: > >> Now think about > >> (length '(a b . "foo")) > > > > Intriguing possibility: Is it necessarily the wrong thing for that to > > return 5? Maybe it should do just that, while a more specific function > > LIST-LENGTH would throw an error. > > Supposing you have a variable *FOO*. You call > > (length *foo*) > => 5 > > Should (elt *foo* 4) give you an error? What should it return if > *foo* is '(a b . "foo")? Could you SETF it? > > What should (length (concatenate 'list *foo* *foo*)) return? One person's intrigue is another's catastrophe. You seem to implicitly suggest that no one is relying on getting an error message here and that the change you propose is compatible. Or else that the compatibility concern is of no consequence. See http://www.nhplace.com/kent/CL/x3j13-86-020.html for historical context. And what should (concatenate 'list *foo* *foo*) return, for that matter. Just because you expect an output list doesn't mean you mean to treat the inputs as lists... CL defines their type to be dynamically inspectable. One reason ELT is interesting is that it's already inefficient for ELT to worry someone will use it to write some algorithm that supposes random access. At least now ELT can sniff at the type it's given and select an appropriate algorithm for doing its work based on that type. If the type can vary recursively, you take away even that minimal class of dynamic optimization. Remember that one reason we signal errors about non-homogeneity of type is to permit programs that assume a local degree of homogeneity at least in the container structure. This, at least, is the motivation for ENDP. ENDP makes very little remaining sense in a world where the type of the object changes as you recurse, since it's all about the intention of it not changing. Questions like this affect the whole fabric of the language if you not only make a random local change but start propagating its implications into changes around it. That fact--of destabilization of time-tested sets of operations--is why we didn't originally do the change to generic, and it's why I stand by that now. I don't have opposition to a new generic set of operations being written as a library for those who like that kind of thing. It's easy enough to do. I don't say languages written with this as a basic premise will fail. I just say that at some point if you morph the core of CL more than a certain amount to suit a new community, you sacrifice the original community for which it is built, most of whom are not clamoring for this change in order to get their work done. Build the experiment first. Find out if people use it exclusively and abandon the old ways. THEN argue that the old unused operators should fall away and yield their names to the new. Then again, since you can build a whole new TRON3K-COMMON-LISP package and seed it with whatever you want without changing CL at all, I'm STILL not sure why you would sacrifice the ability to cross-call old code without modification and not just teach people to start compatibly in TRON3K-COMMON-LISP...
From: M Jared Finder on 17 Jul 2005 11:50 Kent M Pitman wrote: > "Tron3k" <tron3k(a)gmail.com> writes: >>Kent M Pitman wrote: >> >>>Now think about >>> (length '(a b . "foo")) >> >>Intriguing possibility: Is it necessarily the wrong thing for that to >>return 5? Maybe it should do just that, while a more specific function >>LIST-LENGTH would throw an error. > > Necessarily? No. > > Likely? Yes. > > While you can think up uses for it, there are also already tons of non-uses > (that is, errors wanting to be caught). Making those things "work" is the > same as not detecting those errors. I agree with this, but I do not see how that makes genericizing the sequence functions any more difficult. Require LENGTH to be passed a sequence, and not an improper list. If passed an improper list, length should raise a condition of type type-error, just like it does now. This disallows the "clever" implementation of length for lists that you listed: > (defmethod length ((x cons)) (+ 1 (length (cdr x)))) > (defmethod length ((x null)) 0) So don't implement it that way! -- MJF
From: Paul F. Dietz on 17 Jul 2005 11:55
M Jared Finder wrote: > This disallows the "clever" implementation of length for lists that you > listed: > >> (defmethod length ((x cons)) (+ 1 (length (cdr x)))) >> (defmethod length ((x null)) 0) > > > So don't implement it that way! The reason I would like to see functions like LENGTH implemented as generic functions is not so that this clever (but wrong, as Kent points out) implementation could be used, but so that users could add their own sequence types (and, elsewhere, their own streams, and hash tables, and so on). Paul |