Path: utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!samsung!munnari.oz.au!goanna!ok From: ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe) Newsgroups: comp.lang.lisp Subject: Re: Virtues(?) of Lisp syntax Keywords: syntax words,functions Message-ID: <3752@goanna.cs.rmit.oz.au> Date: 14 Sep 90 01:10:22 GMT References: <3368@skye.ed.ac.uk> <1350030@otter.hpl.hp.com> <3408@skye.ed.ac.uk> <3450@syma.sussex.ac.uk> Organization: Comp Sci, RMIT, Melbourne, Australia Lines: 82 In article <3450@syma.sussex.ac.uk>, aarons@syma.sussex.ac.uk (Aaron Sloman) writes: > It's interesting to see this debate surface yet again. > It wasn't till I read this remark of Jeff's that I realised that one > reason I don't like Lisp is that, apart from "(" and ")", Lisp > doesn't help one to distinguish syntax words and function names. I once built a programming language which was a sort of hybrid between Lisp and Pop. In RILL, one wrote e.g. $IF (> X Y) $THEN (SETQ MAX X) $ELSE (SETQ MAX Y) $FI Basically, I used keywords for control structures ($PROC for lambda, $BEGIN for let, $IF, $FOR, $WHILE, and so on) and Lisp syntax for the rest. The parser _was_ better able to notice typing mistakes, and I _did_ make far fewer parenthesis errors than I did with straight Lisp when I later got my hands on it. But that was before I met Emacs. > By contrast the uniform syntax of lisp makes it not so easy to grasp > that car, cdr, sqrt, append, etc. are different beasts from setq, > cond, quote, loop, etc. Hence the tendency to make the kind of > mistake that Jeff describes, i.e. talking about different kinds of > functions. The thing about Pop (as it was last time I used it) is that there is no defined internal form for code. At one end of the spectrum we have "token stream" and at the other end we have "compiled code", and there is nothing in between. I don't know how Pop-11 handles it these days, but in WonderPop the easiest way to write a macro was e.g. form for x:id in e:expr do s:stmts enddo; formvars L; vars L; e -> L; while L.null.not do L.dest -> x -> L; s enddo endform which is roughly the equivalent of (defmacro for (x e &rest s) (let ((L (gensym))) `(do ((,L ,e (cdr ,L))) ((null ,L)) (setq ,x (car ,L)) ,@s))) but it worked rather differently. When the parser found the keyword 'for' it would call the function defined by the form. That function would call .readid to read the identifier for x. It would then check that the next token was "in". It would then call .readexpr to read the expression e. It would then check that the next token was "do". It would then call .readstmts do read the body s. It would then check that the next token was "enddo". Then it would start on the expansion. If any of the reads or tests failed, it would backtrack and try another form (any number of forms could start with the same keyword). What were x, e, and s bound to? *lists of tokens*. The body of the form was processed by making a list of tokens and pushing the lot back on the input token stream. I'm sure I have the names of the reading functions wrong, but that's basically how macros worked in WonderPop, as transformations of sequences of tokens. It works very well. I found Pop "forms" easy to use. But macros aren't the only use for an internal representation. There was no debugging interpreter, for example. (Though you could quite easily trace functions.) > It should also be possible to spell out precisely the cognitive > requirements for particular kinds of learners and users at > particular stages in their development, or for particular kinds of > programming tasks, and establish the strengths and weaknesses of > alternative languages by argument and evidence and not by simply > agreeing to differ. Agreed! > But most designers of programming languages don't think about human > cognitive processes. You should read C.J.Date's comments on SQL... -- Heuer's Law: Any feature is a bug unless it can be turned off.