* Coby Beck wrote: > I think you are touching here on a guiding principle in the design of lisp: > freedom and flexibility over simplicity and safety[1] Where other languages > avoid difficult problems lisp addresses them and IMO does so with only the > complexity that is necessary to define the problem precisely. But really > this should not be any problem whatsoever for anyone who does not really > want that freedom - just don't use it. But when the day comes and you need > it, lo and behold it is there!
Right, and this is the critical point: for some reason people think it's OK for a language to just punt on difficult problems. `Multiple inheritance is hard to get right, and even if you do a lot of work to get it right there are going to be obscure bits. I know: let's just leave it out!' Languages designed like this are small and easy to understand. But there's a problem: the world turns out to be complex and hard to understand, and the programs people write to do stuff in the world need to be complex and hard to understand too. MI for instance, is partly about *modelling things that happen in the world*: I'm a programmer *and* a guitarist *and* a photographer *and* a convenient-thing-for-cats-to-sit-on and about a thousand other things. The program that simulates me needs to model all these multiple properties. Since I'm written in Lisp, all of this is done using MI in CLOS. If I was written in Java, then apart from being four times as large and a tenth as fast, I'd contain a partial, buggy implementation of MI, or more likely *several incompatible* partial, buggy implementations of MI. Imagine if scientists thought like this: `calculus is hard to get right, and even when you do get it right there are some obscure corners: let's just leave it out.' So let's just not bother with any developments in physics since about 1600 then, shall we? The only reason that language designers can make these kinds of decisions without people laughing in their faces is because computer `science' is actually run by the early medieval church, which doesn't hold with too much of this heretical modern stuff itself, and will burn you for heresy if you suggest it.
Well, I'll risk the stake: we need MI and its ilk. So it's hard in places - just get over it: the world is hard in places too. Epicycles can't hack it, in case you hadn't noticed, *however* complex you make them.
I'm learning Common Lisp from Graham, and I'm reading Chapter 11, CLOS, at the moment, so I found it very helpful to be warned that the depth-first, right-to-left, up-to-join algorithm is not the real thing.
I think that the real thing is pretty straight forward. Basically, the programmer lays down the law about the order of the classes, and CLOS does as its bloody well told.
So, (defclass bottom (a b c)) says that
bottom < a < b < c
while (defclass a (c d)) and (defclass b (c d)) say that
a < c < d and b < c < d
There is only one way to stitch these three together
bottom < a < b < c a < c < d b < c < d so
bottom < a < b < c < d
I thought it would be fun to try and write some Lisp to do this calculation.
A least element is an element such that there is no smaller one. Since we are going to be working with partial ordering, there could be several such elements, so the first job is to write a version of MIN that returns a complete list of least elements.
;;;; Take a set, represented by a list, ;;;; and a partial order, represented by ;;;; a function, and return the list of ;;;; least elements ;;;; ;;;; (po a b) returns true when a precedes b ;;;; (defun least-elements (set po); po = Partial Order (let (accumulator) (dolist (candidate set) (when (notany (lambda (other) (funcall po other candidate)) (remove candidate set)) (push candidate accumulator))) (reverse accumulator)))
The hyper-spec atomises (defclass bottom (a b c)) into { bottom<a, a<b, b<c }. I don't need to go so far. It is enough to represent the total order on the classes as a list (bottom a b c). The data defining the partial order is conveniently just a list of lists, with one list per defclass, giving the total order it specifies on the classes it mentions, so I extract the ordering information from
(defclass bottom (a b c)) (defclass a (c d)) (defclass b (c d))
and store it thus
(setq ascending-chains '((bottom a b c) (a c d) (b c d)))
Next I need a function to compute the partial order from the data.
;;;; The partial order is computed by searching ;;;; a list of ascending chains (defun po (smaller larger ) (some (lambda(ascending-chain) (member larger (member smaller ascending-chain))) ascending-chains))
Notice my exploitation of the clever definition of member whereby
(member 3 '(1 2 3 4 5 6 7)) => (3 4 5 6 7)
This is enough to hand crank Jeremy Brown's first example
(least-elements '(bottom a b c d ) #'po) => (BOTTOM) (least-elements '(b c d a ) #'po) => (A) (least-elements '(b c d ) #'po) => (B) (least-elements '(c d ) #'po) => (C) (least-elements '(d ) #'po) => (D)
We can try this on Jeremy's second example
(setq ascending-chains '((bottom a b c) (a c e) (b c d)))
but we get stuck at the end (least-elements '(d e) #'po) => (D E)
This is what the hyper-spec is talking about when it says
When the topological sort must select a class from a set of two or more classes, none of which are preceded by other classes with respect to R, the class selected is chosen deterministically, as described below.
There is a little bit more to computing class precedence lists than just doing what the programmer said. Sometimes there is a tie for which class comes next and we need a tie-breaker.
Then we can cons up a precedence list. The loop start with the list of classes, and moves them, one by one to the precedence list. It is straight forward, unless there is a tie.
I like using comments as function names. The calling code doesn't get cluttered with comments, because it is not cluttered with stuff requiring comments; a double benefit.
Then the tie-break itself. The hyper-spec says
Sometimes there are several classes from SC with no predecessors. In this case select the one that has a direct subclass rightmost in the class precedence list computed so far.
To find the rightmost subclass, we pass in the reverse of the precedence list. So the formal parameter gets named "rev-prec-list", and the call
(tie-break least-elements precedence-list)
is correct, because the do-loop in "precedence-list" is consing it up in reverse order.
Jeremy H. Brown wrote in message ... >"Kenny Tilton" <ktil...@nyc.rr.com> writes: >> Jeremy H. Brown wrote in message ... >> Look, I am confused. This seems like hide-and-seek, with you running out >> into the unguarded space of "CLOS is too complex" then, once spotted, >> dashing back to the home tree of the CPL sort algorithm being surprising in >> corner cases.
>> So far the only specific thing we have you clearly on record about is not >> being able to work out mentally the CPL. otoh, you did mention in the OP >> before/after/around.
>In my original post, I really only singled out those two issues -- MI >prediction, and use of before/after/around. The first one I think has >been beaten to death at this point.
I think if you had started a thread taking issue with the CPL algorithm, proposing an alternative of course, that would have been dandy. But such an obscure issue hardly justifies your slamming CLOS.
>The second one is one of those things where I think the application is >obvious, but in the hands of the inexperienced...
So what? This is programming, not operating a toaster. Inexperienced programmers need to program, study doc, and ask questions on c.l.l. -- not shoot their mouths off denigrating a the best OO tool extant.
>(Don't get me wrong, I know before/after/around is useful.
No sh*t, einstein. But next you say the complexity troubles you. But other places you concede that power is like that. So... nope, can't make sense of your position.
> But there is somewhat more >detail to master than in other systems,...
You are a tool junkie, yes? You /like/ tools that go to eleven. It's one more, isn't it? You don't want to get to ten and have nowhere to go, do you? I am so confused...
> if I want to have generic >functions of the same name but which perform different functions and >take different lambda-lists,
...then you have not read the doc, which explains that is not how this tool works.
>> Plz clarify: What else besides "the internalization of CLOS's CPL >> algotrithm" cannot be mastered with fair and reasonable effort?
>Nothing. That said, it will take more effort --- that is, it will be >harder --- than learning about simpler object models in other >languages, in terms of simply learning the wealth of primitives, in >terms of understanding the larger design space you're working in, and >in terms of learning to work well in that space with those primitives.
This is sad. You seem to be conceding that CLOS (or any tool) is more powerful precisely because of the richer feature set. Suppose now one has been thru Java and CLOS basic training (screw mastery): which will take more effort to /program with/? ie, Given any interesting application, which tool will make it easier to shape a solution to fit the problem?
If your answer is "the more sophisticated tool" [and below I see perhaps it is an open question to you], consider for a moment what it is like to tackle an interesting problem with a tool /insufficent/ to the complexity of the application. Hell on wheels, yes? And the deeper you get into the problem, and as the application gets extended to satisfy requirements, you simply reach deeper levels of hell, yes?
Now we know you have not taken the trouble to learn CLOS, but you might concede that that would be a finite task, and one requiring not a descent into hell, but rather a little perserverance and practice (as opposed to pure spec reading). The effort of learning a tool has an upper bound, the pain of using an insufficient tool does not.
>coming in from knowing other languages, it was (and to some degree >still is) not at all obvious what advantages one gains from investing >the time to learn this wealth of detail.
Doesn't matter what other languages you know. What matters is, what interesting problems have you tackled? If nothing much, the Apple II Integer Basic probably seems to offer everything you could ask of a language.
So maybe we are back at /your/ limitations: inexperienced, uninformed, unread. Funny thing is, if you had had the decency to say upfront that you were clueless and /ask questions/, your "feel the love" remark would have been heartfelt and not sarcasm; folks would have just helped you.
In article <uv6of9x58yp....@suspiria.ai.mit.edu>, jhbr...@ai.mit.edu (Jeremy H. Brown) wrote:
> By approximation rules, I mean a set of simple rules you can more or > less execute in your head as you write a piece of code that will > usually predict how class precedence will actually work out.
The basic rules as presented by Keene are:
1. A class always has precedence over its superclasses. 2. Each class definition set the precedence order of its direct superclasses.
So you write your code with these simple rules in mind. I think worrying too much about CPL before coding is not productive. Actually, whether you define a class foo such that:
(defclass foo (a b) ...) or (defclass foo (b a) ...)
does not matter most of the time. When a precedence order does matter, the CLOS is flexible enough that you can go back, and examine and redefine the classes on the spot. So let's start writing some code. [you should get a copy of Keene first though.]
I am quite busy at the moment, so I only throw a few thoughts into the discussion.
Jeremy H. Brown wrote: > Pascal Costanza <costa...@web.de> writes:
>>I think you're trying to label the wrong things. It's not the >>languages that are simple or complex, but it's the tasks that are >>simple or complex.
> I think that both things are true, actually.
No, I don't think so. Try to use the facilities - not for toy examples that illustrate the corner cases, but for actual real-world examples.
>>Java is a language that is designed for solving simple tasks, while >>Common Lisp is designed for solving complex tasks. However, CLOS is as >>simple as possible for the issues it can solve.
> I'm not qualified to judge that statement at this point.
Then, perhaps, it is wiser to wait until you have gained more experience to be able to judge it from a better perspective. When I entered the world of Common Lisp, and soon thereafter c.l.l not so long ago, I also had some wild ideas how to simplify and "improve" things. Now, I know that this is not a wise approach, but unfortunately it happens all the time. (I know this from the patterns community also, where many pattern newbies want to radically change the pattern approach without actually having a complete picture.)
>>Equally, I don't think you can "master" programming languages, but you >>can rather "master" programming tasks. Java is designed for simple >>tasks, so I cannot master the complex tasks with Java by >>definition.
> I'm not quite sure I buy this argument.
So why do you think are they working on things like genericity, aspect-oriented programming and other extensions to Java? Why do you think the have added reflection to Java, and other more sophisticated "meta" facilities to C#? Such things are eventually needed!
Pascal
-- Pascal Costanza University of Bonn mailto:costa...@web.de Institute of Computer Science III http://www.pascalcostanza.de Römerstr. 164, D-53117 Bonn (Germany)
Kenny Tilton <ktil...@nyc.rr.com> wrote: > Doesn't matter what other languages you know. What matters is, what > interesting problems have you tackled? If nothing much, the Apple II Integer > Basic probably seems to offer everything you could ask of a language.
No way man, Applesoft Basic with FP is *essential*. Going without reals? That's just sick.
Michael, I like hacking unlambda
-- Michael Sullivan Business Card Express of CT Thermographers to the Trade Cheshire, CT mich...@bcect.com
>> Doesn't matter what other languages you know. What matters is, what >> interesting problems have you tackled? If nothing much, the Apple II Integer >> Basic probably seems to offer everything you could ask of a language.
> No way man, Applesoft Basic with FP is *essential*. Going without > reals? That's just sick.
Which begs the question: How many languages and vendors lie in this way by describing their rational number schemes as providing "real numbers"?
CL's reference to "real" is in the "REALPART" function, which does something 'honest' with complex numbers.
C is reasonably honest, in calling its FP values "float" values (or 'double', if you prefer). -- (reverse (concatenate 'string "ac.notelrac.teneerf@" "454aa")) http://www.ntlug.org/~cbbrowne/sap.html "Women who seek to be equal to men lack ambition. " -- Timothy Leary
step...@dino.dnsalias.com (Stephen J. Bevan) writes:
> I can't connect your remark about what I wrote being misleading with > what I wrote since I made no mention of C-level programming in Python. You wrote: > If you use the Java features of Jython then the code doesn't run on > (the C implementation of) Python and hence it doesn't run on just > about every platform, just the ones you have a JVM for. On the other > hand if one programs for the (C implementation of) Python that runs on > just about every platform then one cannot use the Java features of > Jython. Therefore it seems to me that you are comparing Common Lisp > to two languages with two orthogonal features (the ability to use Java > libraries and the ability to run anywhere there is a gcc) not one > which has all features.
I think there's been a simple misunderstanding. If you stick to writing in Python, then it shouldn't matter what you're using, Jython or Python, provided that the libraries are supported. What you said was:
> step...@dino.dnsalias.com (Stephen J. Bevan) writes:
> > [...] On the other hand if one programs for the (C implementation > > of) Python that runs on just about every platform then one cannot > > use the Java features of Jython.
I was making the point that Jython wasn't actually "orthogonal" to Python, but more a superset of it, in the sense that it supports the same kinds of features, and yet takes advantage of the portability, browser pluggability, and library extensibility.
I guess this stuff gets confusing...but I'm not really advocating Python; I'm advocating the way Jython provided an implementation of Python, and in doing so, also provided an easier way to get to the JVM and Java libraries. That's all.
Rather than drop a half-dozen closely related messages into the thread, here's one large response to several recent messages. After this, I'm happy to step out of the thread and let others finish it off. (I'll stick around and answer any questions specifically directed to me, but other than that I'll step out of the thread.)
"Wade Humeniuk" <w...@nospam.nowhere> writes: > "Jeremy H. Brown" <jhbr...@ai.mit.edu> wrote in message news:uv6elat57n4.fsf@suspiria.ai.mit.edu... > > And in my case, at least, I'm a tool junkie --- I want to know how > > they all work, all the details, just so I *know*. Simpler tools are > > easier for me to satisfy my curiousity about; CLOS is going to take > > eons before the itch is fully scratched. (An aside: over time I've > > gotten inherently suspicious of complicated tools; it takes a lot of > > time for me to convince myself the complexity is a net win. Principle > > of least surprise, or something like that. As you can probably tell, > > I haven't really reached that point yet with CLOS, but we'll see how > > things develop.)
> The CMUCL source code is available for you to understand class > precedence. Why don't you just look at the code and see how it is > calculated? You are fretting over nothing.
Well, certainly one hopes that the code is computing it in agreement with the spec. The question is whether reading (or writing, as Alan Crowe did in another recent post) code to compute the CPL will improve one's intuition for the process. Alan, any thoughts on that?
Incidentally, here's a line of thought as to why I (and others) start out intimidated by CL/CLOS. There's two kinds of knowledge: knowing something, and knowing where to look something up. (This says nothing about knowing how to use that knowledge well, of course.)
Between the Hyperspec, widely-available CL/CLOS implementations, etc., a bit of familiarization is probably enough to create the second kind of knowledge pertty quickly. What some of us have (unfortunately) come to expect from experience with languages such as C, Scheme, and Java[*] is that with respect to the core of the language, at least, the transition from the latter type of knowledge to the former type is a relatively short, and relatively complete process.
Those of us with this expectation --- however dumb it may be --- are then spooked when we realize early on that (a) the language core for CL is significantly larger than for these other languages, and (b) CPL, at least, is part of the core that one may never completely move into the former class of knowledge.
So, there you have it, a theory of why some of us have an emotional/visceral reaction: violated/unrealistic expectations.
[*] Actually, if people want to pick on Java for having unknown and unknowable corners, I would recommend they start with the threading/synchronization/memory model. See, for instance, http://csg.lcs.mit.edu/pubs/memos/Memo-428/memo-428.pdf I think most Java programmers remain blissfully unaware of this attrocity.
------
Fred Gilham <gil...@snapdragon.csl.sri.com> writes: > > Fair enough, although how frequent the exceptional cases arise is a > > legitimate criterion for judgement as well. As yet, I have no real > > sense of how often these arise in practice with CLOS; I was spooked > > early on by the fact that Winston and Horn had to dedicate an entire > > appendix to explain how the class precedence list is actually > > computed. I fully grant that it may turn out to be irrelevant 99% > > of the time --- but it is spooky to a newcomer (or at least this > > newcomer) to even be told that the situation exists.
> I think you will find Richard Gabriel's paper, "Lisp: Good News Bad > News How To Win Big" helpful here. A quotation from that paper > follows: > [clip]
The clasic "Worse is Better" paper! It's mandatory reading around here; I've probably read it 3 times in the last few years, but not since I'd developed interest/time to actually try to learn CL. Thanks for reminding me of it.
Upon rereading it now, I'm struck by how it contains many statements likely to frighten newbies away from CL, e.g. "We've seen that the right thing attitude has brought us a very large, complex-to-understand, and complex-to-implement Lisp -- Common Lisp that solves way too many problems," or "In Lisp it is very easy to write programs that perform very poorly; in C it is almost impossible to do that." And this from a master of the language!
I wonder how many university students get their first taste of lisp with this paper and go off to learn C/C++ and UNIX without ever looking back. I imagine this one paper scares away more people than a dozen newbies like me saying "CL [or CLOS] is hard, let's go shopping."
> The idea here is that when you see something like the appendix on CPL > you are in the presence of "the right thing." Note especially that > when one trades off between simplicity and completeness, completeness > is supposed to have some degree of priority. So this appendix is > telling you that CLOS will do "the right thing" in a fairly obscure > area. The existence of this appendix shows how "the right thing" > mentality operates.
> But if you are used to a "worse is better" approach you will see this > same appendix and think, "If they are covering this case in some > detail, it must be really important to understand it, because it will > probably come up often."
> But it won't.
> As you use Lisp (and other systems) you get a feel for things like > this. Personally when I saw that appendix some years ago, I thought, > "In the unlikely event that I ever have this problem it's nice to know > that there's somewhere I can look to see what's going on."
Point taken, and certainly I tend to come at things from a worse-is-better philosophical standpoint. I will attempt to realign my expectations for this learning process.
Gabriel himself seems to have wandered back and forth a lot as to where he actually stands on the matter; the whole, fascinating saga, -- including debating himself in papers written under assumed names! -- is described at http://www.dreamsongs.com/WorseIsBetter.html
------
Tim Bradshaw <t...@cley.com> writes: > * Jeremy H Brown wrote:
> > So maybe you've just identified one of the key simplicity-vs.-power > > issues that make it easier to "master" Java than CLOS: whenever > > something potentially confusing comes up, Java simply says "you can't > > do that", while CLOS provides a mechanism (a perhaps > > necessarily-complex one) for managing the situation.
> Right. And this is one of the things that I (and others) said ages > ago. CLOS is only complicated if you want to do complicated things. > Like MI - it's much simpler in Java because it isn't there at all.
Check.
> And I hear it's quite exciting in C++.
Although I've used C++ extensively, I've avoided the MI parts --- partly from lack of need (or at least, lack of realizing I had the need), and partly due to the gagging reaction. C++ is my least favorite language.
------
j...@iki.fi (Janne Rinta-Mänty) writes: > Jeremy H. Brown 2002-10-14T02:01:46Z: > > [*] This approximation scheme, which I was taught by the same book > > these examples come from, is as follows: [...]
> Do they say /why/ they have an approximation scheme in the book? I > can't think of any reason for it: it doesn't seem to be easier to use > than the real thing and clearly it gives wrong results.
They don't explicitly list a reason; my read was that this enabled you to figure out how your back-of-the-coaster class hierarchy would work out in practice without having to haul out a laptop at the bar.
------
"Coby Beck" <cb...@mercury.bc.ca> writes: > I think you are touching here on a guiding principle in the design of lisp: > freedom and flexibility over simplicity and safety[1] Where other languages > avoid difficult problems lisp addresses them and IMO does so with only the > complexity that is necessary to define the problem precisely. But really > this should not be any problem whatsoever for anyone who does not really > want that freedom - just don't use it. But when the day comes and you need > it, lo and behold it is there!
> Right, and this is the critical point: for some reason people think > it's OK for a language to just punt on difficult problems.
This is very much the worse-is-better approach on display. Viral simplicity.
> Well, I'll risk the stake: we need MI and its ilk. So it's hard in > places - just get over it: the world is hard in places too. Epicycles > can't hack it, in case you hadn't noticed, *however* complex you make > them.
A question: My brain by and large hasn't been stretched in the MI direction yet, so I don't have a good sense of what applications it tends to get used in. E.g., in the past I've done a fair bit of compiler work (mostly for tasteless C-like languages.) I haven't felt like I was losing for lack of MI, but then again I don't know the tool well. Has anyone here used MI for a compiler type project? What for? Modelling the real world is the most obvious (to me) application of MI; what else have you used it for in practice?
------
Pascal Costanza <costa...@web.de> writes: > Hi Jeremy,
> I am quite busy at the moment, so I only throw a few thoughts into the > discussion.
Thanks for taking the time. It's hard to keep up with the pace of this newsgroup.
> Jeremy H. Brown wrote: > No, I don't think so. Try to use the facilities - not for toy examples > that illustrate the corner cases, but for actual real-world examples.
That's the goal. I'm mostly putzing around getting familiar with the environment at the moment, but I hope to do something larger shortly. (If anyone has suggestions for an application the world desperately needs and that CL is well-suited to, let me know, maybe I'll take a stab at it.)
Dave Bakhash <ca...@alum.mit.edu> writes: > I think there's been a simple misunderstanding.
Indeed there has. I think it is based on the following :-
o it runs on just about every platform...probably even more portable than CLISP (it basically runs wherever there's a working gcc).
This was the last item in your list of advantages of Python over CL. All the other advantages were common to both the Java-based version (Jython) and the C-based version, but as written the above is specific to the C-based version. If you had never mentioned the above advantage and written Jython everywhere (i.e. ignored the original C-based version of Python completely) then I would not have commented on this point at all.
I would still have followed up with the note about Kawa and SISC since if one is happy with to programming for a single-implementation language such as Jython then Kawa and SISC both share many of the features you list as advantages for Jython, with one obvious advantage from a Lisp perspective being that syntactically and semantically they are members of the Lisp family of languages (let's not get too picky about the fact that they are members of the Lisp-1 rather than Lisp-2 subsets).
> Well, certainly one hopes that the code is computing it in agreement > with the spec. The question is whether reading (or writing, as Alan > Crowe did in another recent post) code to compute the CPL will improve > one's intuition for the process. Alan, any thoughts on that?
Writing it helped me alot.
I am curious as to whether my posting my code helped anyone else. I hope to write some intermediate level tutorials to help other persons learn Common Lisp. If it is the case that writing code oneself helps, but reading other persons code doesn't help, then I have an alternative way of presenting the subtleties of precedence list computation. It uses lots of single inheritance classes to create a striking visual pattern and give the account some narrative drive. Here is my first draft of the end of my tutorial:
######## start of draft of end of tutorial ############
... it is blocked on `fs3' by `nuisance', and moves on to doing the second stack of classes, before coming back and finishing the first stack.
Now we can make mischief. I've taken the `nuisance' class out of `stack-base', and moved it so that it annoys `main', a class that inherits from `stack-base'
shows that `main' has been affliced by `nuisance'. Its class precedence list has to break off from enumerating the first stack of classes, do the second stack of classes and finish off `fs3', `fs4', and `fs5' after `nuisance'. The classes in the second stack have jumped into the middle of the enumeration of the first stack of classes. This could be a major shock to the programmer who wrote `stack-base', and stop the class working when it is subclassed in this way.
########## end of draft of end of tutorial ############
My main qualification for writing tutorials is that I am learning Lisp myself. Thus I an intimately acquainted with the confusions that assail and distress newbies. Although this is a valuable qualification, it is has disadvantages. In particular I will be depending on the members of this list to catch my technical errors. This worries me. There is plenty of enthusiasm for spotting technical errors in short postings put directly on comp.lang.lisp. However, if I write some lengthy tutorials, etiquette will require that I put them on my website and post the URL to the list. Are there enough folk willing to follow a link, read a long tutorial and then point out the technical errors?
> > Do they say /why/ they have an approximation scheme in the book? I > > can't think of any reason for it: it doesn't seem to be easier to use > > than the real thing and clearly it gives wrong results.
> They don't explicitly list a reason; my read was that this enabled you > to figure out how your back-of-the-coaster class hierarchy would work > out in practice without having to haul out a laptop at the bar.
I'm sure that I can come up with an explanation of the exact scheme, suitable for beginners. It might take a few more tries though :-(
* Alan S. Crowe : | shows that `main' has been affliced by `nuisance'.
Excellent example.
| My main qualification for writing tutorials is that I am learning Lisp | myself. Thus I an intimately acquainted with the confusions that assail | and distress newbies.
The problem with this is that you meet these things in a totally random order. The point of a tutorial is to make order of the chaos. I am fairly strongly convinced that the best way to make that order is to be very knowledgeable and very observant when you try to teach a lot of people the same material and have time to follow up on them to see how they do and to correct your own mistakes. Hence I am extremely doubtful of teaching material that has been written by other than teachers and much prefer to fight my way through reference works when I have enough glimpses of the order to at least not get lost in the chaos. However, as a shining example of an excellent instruction on CLOS that helped me sort out the order of the dense specification, Sonya Keene's book only gets higher commendations from me as time goes on while the misnamed «ANSI Common Lisp» by Paul Graham gets lower.
| There is plenty of enthusiasm for spotting technical errors in short | postings put directly on comp.lang.lisp. However, if I write some | lengthy tutorials, etiquette will require that I put them on my website | and post the URL to the list. Are there enough folk willing to follow a | link, read a long tutorial and then point out the technical errors?
People who did you this kind of service deserve to be co-authors at the very least. But when you do this, you implicitly argue that none of the existing material is good enough and ask people who may think it is better than yours to help make yours better than everything else. This may be a tall order. I doubt that you want to make this argument explicitly, however, so I instead wonder what tutorials and other works on CLOS you have read before you decided to write your own tutorial.
-- Erik Naggum, Oslo, Norway
Act from reason, and failure makes you rethink and study harder. Act from faith, and failure makes you blame someone and push harder.
Alan S. Crowe wrote in message <86d6q9kqem....@cawtech.freeserve.co.uk>... >jhbr...@ai.mit.edu (Jeremy H. Brown) writes:
>> Well, certainly one hopes that the code is computing it in agreement >> with the spec. The question is whether reading (or writing, as Alan >> Crowe did in another recent post) code to compute the CPL will improve >> one's intuition for the process. Alan, any thoughts on that?
>Writing it helped me alot.
Let me ask you this. Do you thnk you need an intuition for the corner cases of the CPL derivation?
I have programmed CL for about seven years now and twice developed GUI frameworks in which I beat on multiple-inheritance like I was its daddy, and until this silly thread came up (1) i did not know the algorithm and (2) i never got surprised by how a class's CPL panned out (in generic function dispatch and other manifestations of the CPL). Mind you, I regularly get myself into a knot with a god-forsaken hierarchy and /then/ I get surprises, but by then I have been aware for a while that I needed to refactor the whole mess and the surprise just pushes me over the edge (unless I kludge a workaround).
When I look at published examples which manifest CPL surprises, they are thoroughly unconvincing semantically. As in, screw the CPL, lose that hierarchy! That's OK for those papers since they just want to show that surprises are avoidable, so all that matters is that they show a corner case which a beter algorithm can handle without surprises. But such stuff does not impact real-world development, and being able to intuit the CPL over the keyboard is a real-world development concern, so as far as me being able to /intuit/ the CPL over the board -- why?
As has been my experience, I wager any real world surprise will appear only in a class hierarchy needing fixing anyway, which will eliminate the surprise. (Yes, this is a Challenge.)
As for /intuiting/ how (defclass a (b c)()) will pan out, that is not going to happen anyway. Any case hairy enough to produce a surprise will require some scratch paper and a pencil to work out, even with a surpriseless algorithm. For one thing, the source for the defclass forms of b and c likely will not be at hand.
Bottom line: this is not a newbie concern, this is not even a concern for a seasoned CLOS developer. it's just a curiosity.
> Are there enough folk willing to >follow a link, read a long tutorial and then point out the >technical errors?
You would not be the first to go this route. The amount of feedback you get may depend on what folks think of what they find when they get to your site; the better it looks, the more feedback you will get.
>I'm sure that I can come up with an explanation of the exact >scheme, suitable for beginners.
I'll be interested in the example class hierarchy. :)
"Kenny Tilton" <ktil...@nyc.rr.com> writes: > Let me ask you this. Do you thnk you need an intuition for the corner cases > of the CPL derivation?
One poster offered some class definitions including
(defclass c (d e)())
and ended by computing the class precedence list for his most specific class as ...e...d...
That just had to be wrong, because CLOS always respects the local ordering; d will always come before e, whenever c is amongst the superclasses.This felt to me like a bug in the book the poster had been studying.
> As has been my experience, I wager any real world surprise will appear only > in a class hierarchy needing fixing anyway, which will eliminate the > surprise. (Yes, this is a Challenge.)
I've found your comments very helpful. They suggest to me a three part structure for a tutorial:
Part I: Bring out the importance of the local order implied by the list of superclasses.
Ia Typically the set of superclasses is only partially ordered by the local orderings of the direct superclasses.
Ib Typically each generic function is defined on a proper subset of the set of superclasses.
Ic Typically a generic function is defined on a subset of the superclasses that /is/ totally ordered by the local orderings. So for each generic function, one can work out the applicable method, without needing a total ordering on the superclasses.
Teach the skill of using the local orderings to find applicable methods on a generic function by generic function basis.
Part II: Sometimes a generic function is defined on a subset of the superclasses that is only partially ordered by the local orderings.
Teach suspicion. Why is the code getting so complicated? Does the application push the programmer to write such subtle code, or is the programmer letting the code get in a tangle, with complications not inherent in the application?
Perhaps there is a conceptual error in the design of the program and there are really two generic functions. Give them different names, and watch the problem vanish.
Part III: Sometimes one really does need to know CPL.
But not often, so go away and write some code, and come back if you need to.
Grandparents before uncles
That covers most cases, so go away and write some more code, and come back again if you need to.
Finish half done classes before going on to new ones
How the algorithm accomplishes this
Non-monotonicity.
> Good luck with the tutorial project, btw.
Thanks. I've got a tutorial on `let' for parenphobic beginners nearly finished, so I'm going to concentrate on finishing it, and leave CLOS for a while.
Erik Naggum <e...@naggum.no> writes: > Excellent example.
Thank you.
> However, as > a shining example of an excellent instruction on CLOS that helped me sort > out the order of the dense specification, Sonya Keene's book only gets > higher commendations from me ....
I should leave off writing about CLOS until I have checked out this book. No point reinventing the wheel.
> People who did you this kind of service deserve to be co-authors at the > very least.
Standard book practise is to acknowledge one's technical reviewers in the preface, not to list them as co-authors.
> But when you do this, you implicitly argue that none of the > existing material is good enough
This inference is invalid. The merit of a tutorial is a function of the student. Consequently tutorials are not, in general, comparable. For example, Alice may prefer Issiah's tutorial to Jacob's, while Bob may think Jacob's much superior to Issiah's. There is no uncontroversial ordering. The strongest inference to be drawn directly from my desire to write my own tutorials is that I do not believe that all tastes are fully catered for.
* Alan S. Crowe | Standard book practise is to acknowledge one's technical reviewers in the | preface, not to list them as co-authors.
Standard book practice is for the most knowledgeable people to write the book and for reviewers to be at approximately the same level of general expertise, but not vastly superior to the author in specific expertise.
I have reviewed books that were published and manuscripts for books that I recommended against publishing. I have reviewed graduate and doctorate theses and advised students at both levels in specific areas. People have called on my expertise in this fashion for more than 10 years. I have worked with and in the publishing industry and have written four chapters on a book on SGML (with an incredibly helpful copy-editor that taught me more about English than years of study) that was not published because writing it caused me to decide to leave the field because it was impossible for me to work with such an inferior technical solution -- something I had glossed over while I only helped people understand its more complicated points. I am still credited in several books on SGML for having helped the authors both understand points better and for suggesting improvements to their writing. Never have I seen a book published by a novice for novices, nor heard of such a thing, but that does not mean it does not exist -- the likelihood that I would purchase it or read it is zero, as it would undoubtedly have an off-putting title and cover, probably including the target audience "dummies" or "the complete idiot". I recently reviewed a book in which the author could only be understood to apologize for his lack of mastery of the subject when he chatted endlessly about how hard it was to linearize the material and where he used more promises of what was to come and repetitions of what he had discussed than actual new information in each paragraph, how this and that feature in the topic he discussed "is not easy" to use and understand. It was torture to read and try to lift it to some readable level. I was quite handsomely rewarded for my effort but the book may never be published. I think I speak with some authority on how reviewers are treated.
When the reviewer has done much of the writing, or coaching, or even education of the author, the reviewers deserve to be named co-authors. I quite firmly stand by this. I know book publishing, and your tutorial is, with all due respect a tutorial on the Net, not a published book.
| > But when you do this, you implicitly argue that none of the | > existing material is good enough | | This inference is invalid.
No, it most certainly is a valid inference. Such terminology belongs to the realm of logic, and logic is concerned with structure of the argument, not with the truth of its premises. An inference does not become invalid simply because you disagree with parts of it. Acquire precision!
| The merit of a tutorial is a function of the student.
What a odd statement.
| There is no uncontroversial ordering. The strongest inference to be | drawn directly from my desire to write my own tutorials is that I do not | believe that all tastes are fully catered for.
Which even more strongly suggests that you enumerate what you have already read and, with no small amount of irony, explain why you are still a "newbie" in your own eyes.
-- Erik Naggum, Oslo, Norway
Act from reason, and failure makes you rethink and study harder. Act from faith, and failure makes you blame someone and push harder.
Erik Naggum <e...@naggum.no> writes: > Never have I seen a book published by a novice for > novices, nor heard of such a thing,...
You have not heard of this thing from me. I have thirty years of experience of programming computers in languages other than Lisp. My first attempt to learn Lisp was in 1978, learning from John R. Allen's book, Anatomy of LISP. Since I did not have access to an implementation, I tried to write one in assembler for my 6809 machine. My garbage collector, based on the Schorr-Waite graph marking algorithm, passed a few test cases, but other commitments supervened. I never had a prompt to type at.
Now, 24 years later, I have a prompt to type at, for the first time. I find that I am no better at herding brackets than the distressed teenage newbies who sometimes post on this list, but I am learning much faster, because I have overcome analogous difficulties many times before. I should write about taming the paren panther, the fierce funcall, and the dangerous defvar now, while the wounds are healing. In a year's time, the scars will have faded, and I will no longer remember what made it seem so hard at the time.
a...@cawtech.freeserve.co.uk (Alan S. Crowe) writes:
> You have not heard of this thing from me. I have thirty > years of experience of programming computers in languages > other than Lisp. My first attempt to learn Lisp was in 1978, > learning from John R. Allen's book, Anatomy of LISP.
Good heavens. A great book but definitely the deep end of the pool.
> Since I did not have access to an implementation, I tried to write > one in assembler for my 6809 machine. My garbage collector, based on > the Schorr-Waite graph marking algorithm, passed a few test cases, > but other commitments supervened. I never had a prompt to type at.
But you had a good time and learned a lot, I'll bet.
> Now, 24 years later, I have a prompt to type at, for the first > time. I find that I am no better at herding brackets than the > distressed teenage newbies who sometimes post on this list, but I am > learning much faster, because I have overcome analogous difficulties > many times before. I should write about taming the paren panther, > the fierce funcall, and the dangerous defvar now, while the wounds > are healing. In a year's time, the scars will have faded, and I will > no longer remember what made it seem so hard at the time.
I agree. The idea would be to write the book immediately, while you still have the newbie attitude, but resist the urge to publish for a couple of years. During that time polish it and flesh it out while trying to avoid the arcana. As Erik points out, a good beginner book really needs to be polished by use and feedback. If written for a raw beginner, IMHO it should not be too dry or longer than 200 pages. The temptation is to be too inclusive.
I find "The Little Lisper" a pretty tedious for a beginner, even though it's short.
Maybe one of the reasons that C has been so successful is K&R: not too long, but complete and very readable.
I had a chance to work with an older gentleman who had never used a computer. In less than six months he progressed (with minimal coaching from me -- I can't claim success :) to installing Debian Testing on his machine. It was interesting to see the things that were causing him trouble.
What's the best raw beginner book on Common Lisp? Or maybe its not a suitable beginner's language?
> What's the best raw beginner book on Common Lisp? Or maybe its not a > suitable beginner's language?
That's an interesting question. I think you need to understand the problems some of the Common Lisp constructs are trying to solve before you can see the necessity of the complexity of the solution. Common Lisp tries to hit the 'as simple as possible, but no simpler' spot and succeeds on most cases, but it isn't immediately obvious if all you measure it by are toy programs.
-- Hai koe, zei de stier, Kom mee met mij in de wei, Dan zijn we tweezaam. Lieven Marchand <m...@wyrd.be>
On Wed, 25 Sep 2002 01:56:59 GMT, Kenny Tilton <ktil...@nyc.rr.com> , undoubtedly inspired by the Great Cthulu wrote:
>All that is nice (and I mean that), but what i meant was, all these >people working on Python could instead be working on a free CL >implementation, saving themselves the effort of defining a new language. >They would even have CMUCL to start from, a pretty decent head start.
And how much market share or mind share does CMUCL have, compared to Python or Ruby ?