Path: utzoo!attcan!uunet!seismo!esosun!jackson From: jackson@esosun.UUCP (Jerry Jackson) Newsgroups: comp.lang.lisp Subject: Re: What's the value of lexical scoping? Message-ID: <209@esosun.UUCP> Date: 17 Jun 88 23:11:51 GMT References: <24508@ucbvax.BERKELEY.EDU> <515@dcl-csvax.comp.lancs.ac.uk> <199@esosun.UUCP> <525@dcl-csvax.comp.lancs.ac.uk> Organization: SAIC, San Diego Lines: 124 In-reply-to: simon@comp.lancs.ac.uk's message of 16 Jun 88 09:52:37 GMT I must admit that after reading the measured response of Simon Brooke to my *inflammatory* posting I felt somewhat abashed, but I would still like to respond to some of his points... I think we are converging on the good and bad points of both sides.. >>CL supports dynamic binding for those cases where >>it is useful (I admit they definitely exist), although dynamic binding >>is quite clearly a *BUG* (the names you give to local variables should not >>matter...) >> >If you wish to gain information from your environment, then clearly, the >names of the symbols you use do matter. If you bind your locals either >in an arg list or in a let statement, then they don't matter. If you >*don't* do this, then you are using globals, which will get you into equal >trouble no matter what binding scheme you use. So this argument is simply >not tenable. I agree that we can debate (and disagree) about which binding >scheme is preferable, but it makes no sense to describe those you don't >like as bugs. I would like to elaborate on why I called this a *bug*. It is not that I just don't like it. Here is an example of what I was talking about -- (defun foo (l) (my-mapcar #'(lambda (z) (eql z l)) '(1 2 3 4))) (defun my-mapcar (f l) (if (null l) nil (cons (funcall f (car l)) (my-mapcar f (cdr l))))) With lexical scoping, the result of: (foo 2) => (nil t nil nil) With dynamic scoping, the result of: (foo 2) => (nil nil nil nil) With dynamic scoping, it is impossible to write a general procedure which takes functional arguments that doesn't have this problem. This is why I said it's a bug -- it violates the notion that the names you pick for *locals* shouldn't matter -- (notice that "l" in this case was bound in the arglist) >>PROG,GO -- For people who never have to write powerful tools I would >>agree that these are not necessary, but if you had ever tried to compile >>a special purpose language to lisp and make it reasonably efficient, you >>would appreciate the value of having things like PROG and GO as >>compilation targets >> >Whilst we still programme largely for von Neumann architectures, there is >need for an iterative construct in LISP; however, there are many more >elegant iterative structures than PROG available to the designers of >modern LISPs. If you are using PROG for any purpose other than iteration, >then (if I were advising you - and of course, you might not accept my >advice) I would suggest that you probably need a clearer analysis of your >problem. Myself, I would never use GO or GOTO in any language. As I said in my original statement, I am not advocating the use of the abominable "go"-man in user code. What I am saying, is that "go" is a useful target for compilers for embedded languages -- (I have recently written a compiler for a lisp-based prolog that compiles to lisp which takes advantage of this...) In fact, personally I don't much like iteration at all... That's why I want implementors to be able to produce tail-recursive control structures (even for embedded languages) >>SETF -- I can't believe my eyes... This is one of the BEST things about >>CL... I don't know what to say. Anyone who has actually USED CL with setf >>for a while knows what I'm talking about. >> >So you actually like overwriting cons cells without knowing what else is >pointing to them !? Either you aren't serious, or you haven't looked at >what SETF does. We all *know* REPLACs are dangerous; we all use them with >care (I hope). But SETF allows us to overwrite a cons cell without even >getting hold of it to identify it first! That is *terrifying*! and you are >going to put that horror into the hands of the innocent? On the contrary, I think that the benefits of SETF are most apparent when you *do* know your target -- (I'm not really sure it is even possible to do the opposite -- SETF is pretty dumb.. you have to tell it where the cell you want changed is and it has to know at compile time where that is) Yes, RPLAC's are bad. SETF is basically the same as the assignment mechanism in a more typical language like 'C': a[i].wow = 5; => (setf (wow (elt a i)) 5) Is this bad? BTW: There are things *I* don't like about CL -- 1) packages -- The package system of CL is based on the wrong idea.. A programmer doesn't care if someone else uses the same symbol as *data*; He only cares if it is a variable name or a function name, etc. Since what is important is the set of *bindings* for a symbol, an environment system would be more appropriate. 2) #' -- By distinguishing function bindings from variable bindings, CL makes many uses of lexical scoping awkward and nearly opaque (as well as requiring extra special forms) 3) the equality predicates -- I admit that I don't have a good answer to this problem, but I think equalp was not well thought out (couldn't we at least have a function just like equalp except that it is case-sensitive for strings; or an option to equalp? -- I know, I know, everyone has his own set) 4) A nit-pik -- has anyone ever found a use for the top level form: '-' ? However, if you consider the magnitude of the task of designing this language, they did pretty well. (I never thought I'd say this -- I used to be an Interlisp-D hacker..) +-----------------------------------------------------------------------------+ | Jerry Jackson UUCP: seismo!esosun!jackson | | Geophysics Division, MS/22 ARPA: esosun!jackson@seismo.css.gov | | SAIC SOUND: (619)458-4924 | | 10210 Campus Point Drive | | San Diego, CA 92121 | +-----------------------------------------------------------------------------+