Path: utzoo!attcan!uunet!mcsun!ukc!icdoc!syma!aarons From: aarons@syma.sussex.ac.uk (Aaron Sloman) Newsgroups: comp.lang.lisp Subject: Re: Virtues(?) of Lisp syntax Summary: response to Jeff Dalton on readability of "short" procedures Keywords: syntax words, functions, redundancy, cognitive engineering Message-ID: <3465@syma.sussex.ac.uk> Date: 16 Sep 90 12:58:54 GMT References: <3368@skye.ed.ac.uk> <1350030@otter.hpl.hp.com> <3408@skye.ed.ac.uk> <3450@syma.sussex.ac.uk> <3427@skye.ed.ac.uk> Organization: School of Cognitive & Computing Sciences, Sussex Univ. UK Lines: 145 jeff@aiai.ed.ac.uk (Jeff Dalton) (14 Sep 90 20:21:11 GMT) commented on my remarks on the syntactic poverty of Lisp. (From me:) > >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. > (From Jeff:) > Actually, Pop-11 doesn't do much along those lines either. > It's not like it uses a different font for them (cf Algol). I agree that Pop doesn't make the syntax words look different in isolation. That wasn't what I meant (though perhaps that would be a good idea especially in printed text). Rather, I meant that in Pop-11 the syntax words (or many of them) play an obviously different role in syntactic constructs, e.g. having matching brackets and associated keywords. This helps students grasp that they have a different role from function names ie. they are concerned with how program text is grouped into sub-structures with (e.g.) control relations between them (evaluating THIS expression determines whether THAT one is executed, or whether iteration continues, etc.) Getting a good conceptual understanding of all this takes students some time. Using collections of related syntax words that indicate different kinds of syntactic "fields" or "contexts" in program text, seems to help. (I now think this is more than just an aid to short term memory as suggested in my earlier message. But the point needs more thought.) > .... (From me:) > >E.g. the use of essentially redundant keywords like "then", "elseif" > >and "else" in conditionals, and the use of distinct closing brackets > >like "endif", "endwhile" that remind you what sort of construct they > >are terminating, has a particularly important consequence. It > >reduces short term memory load, [...] (From jeff:) > Now, there's no doubt soemthing to what you say. However, I don't > think there's as much to it as you suppose. > > One of the *mistakes* some people make when writing Lisp is to > try to add the redundancy you describe by putting certain close > parens on a line of their own followed by a comment such as > " ; end cond". It makes the code *harder* to read, not easier. (He goes on to justify this by saying that indentation plus a good editor helps, and that GOOD lisp programs have short procedure definitions and that adding such comments makes them longer and harder to take in.) > Of course, it's no doubt possible to write procedures (such as ones > that are too long) where end markers might make a difference. But > is is also possible to avoid those cases, just as it is possible to > avoid other bad practices. I agree that a good editor helps a lot (though people often have to read code without an editor, e.g. printed examples in text books, etc) and I agree that well-written short lisp definitions (e.g. up to five or six lines) are often (though not always) easily parsed by the human brain and don't need much explanatory clutter. But I doubt that it is always desirable or possible to build good programs out of definitions that are short enough to make the extra contextual reminders unnecessary. It probably depends on the field of application. E.g. I suspect that in symbolic math programs you can get away with lots of short procedures, whereas in graphics, vision, operating system design, compilers(??) and building complex interactive programs like text editors and formatters, some at least of the procedures are going to have longish stretches of nested case analysis, several nested loops, etc. Even Common_Lisp_The_Language (second edition) has examples that I think are long enough to benefit from these aids that you say are unnecessary. (Scanning more or less at random for pages with lisp code, I found examples on pages 340-349, 667, 759, 962 and 965. Or are these just examples of bad lisp style? (I've seen much worse!) > > Moreover, if you want to argue for the advantages of distinct closing > brackets it's not necessary to compare Pop-11 with Lisp. How about > comparing it with a language that uses "begin" and "end" (or "{" and > "}") for everything rather than "endif" "endwhile", etc.? Yes, Pascal and C (especially C) are open to some of the same objections as lisp, because they don't have sufficient disinct opening and closing brackets, though the use of "else" is a step in the right direction. This is why many programmers using these languages add the kinds of comments you disapprove of. (Some Pop-11 programmers do also.) ML is another language which, from my observations and reports of student difficulties, has a syntax that is too economical, though in a very different way from Lisp. I don't know the language well, but I think it requires the reader to depend too much on remembered operator precedences in different contexts. This is no problem for a computer but very hard for people. So students often have great trouble understanding how compile-time error messages relate to the code they have written, which "looks" obviously right to them. Additional use of brackets might help. (Perhaps this syntactic poverty will prevent ML ever being used widely for large scale software engineering.) Prolog has yet another kind of syntactic poverty, inherited from its dependence on a logical interpretation. (E.g. textual order has very different procedural meanings depending on context: within a rule concatenation means something like "and then", whereas between rules with the same predicate it means something like "and if that fails then try...") My general point is that human perception of complex structures is easiest and most reliable when there is well chosen redundancy in the structures, and most difficult and error-prone when there isn't. However, as you point out, too much redundancy can sometimes get in the way, and we don't yet know the trade-offs. The use of indentation in lisp and C is an example of redundancy that is an essential aid for humans although totally unnecessary in theory. But it is only one type of redundancy, and is useful only on a small scale (as you imply). (Maybe this stuff should have been cross-posted to comp.cog-eng, since cognitive engineering is what we are talking about.) For the record, I should also say that I don't think there's much difference in readability between the following: a(b(c(d, e), f(g, h))) [Pop-11 and Pascal, etc] (a (b (c d e) (f g h))) [Lisp] Though I do find the latter more visually elegant. > I think > there are too many other differences between Pop-11 and Lisp. Yes, there are other differences, including the differences mentioned by Richard O'keefe to which I'll respond in another message. Aaron