[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: "Python for Lisp Programmers"
Date: Sun, 9 Dec 2001 15:25:40 -0500 (Eastern Standard Time)
From: "S. Alexander Jacobson" <alex@shop.com>
On Sun, 9 Dec 2001, Michael Vanier wrote:
> Even though I love python and use it all the time, I'll second Shriram
> here. I spent some of the last term teaching scheme to undergrads, and
> none of them had a problem with the parenthesized syntax after about the
> first two weeks. I think the problem is that most people have a knee-jerk
> negative gut reaction to seeing all those parentheses, and they never make
> it past that stage.
Historical question: Ergonomically, Parentheses are annoying because they
require constant use of the SHIFT key. Square brackets would have been a
better choice. Who chose parentheses and why?
Here is what John McCarthy had to say about it:
The programs to be hand-compiled were written in an informal notation
called M-expressions intended to resemble FORTRAN as much as possible.
Besides FORTRAN-like assignment statements and go tos, the language
allowed conditional expressions and the basic functions of LISP.
Allowing recursive function definitions required no new notation from
the function definitions allowed in Fortran I - only the removal of the
restriction - as I recall, unstated in the FORTRAN manual - forbidding
recursive definitions. Tye M-notation also used brackets instead of
parentheses to enclose the arguments of functions in order to reserve
parentheses for list-structure constants. It was intended to compile
from some approximation to the M-notation, but the M-notation was
never fully defined, because representing LISP functions by LISP lists
became the dominant programming language when the interpreter later
became available. A machine readable M-notation would have required
redefinition, because the pencil-and-paper M-notation used characters
unavailable on the IBM 026 key punch.
...
Another way to show that LISP was neater than Turing machines was to
write a universal LISP function and show that it is briefer and more
comprehensible than the description of a universal Turing machine.
This was the LISP function eval ... Writing eval required inventing
a notation representing LISP functions as LISP data, and such a notation
was devised for the purposes of the paper with no thought that it would
be used to express LISP programs in practice. ...
...
S. R. Russell noticed that eval could serve as an interpreter for LISP,
promptly hand coded it, and we now had a programming language with an
interpreter.
The unexpected appearance of an interpreter tended to freeze the form
of the language, and some of the decisions made rather lightheartedly
for the ... paper later proved unfortunate.
Another reason for the initial acceptance of awkwardnesses in the
internal form of LISP is that we still expected to switch to writing
programs as M-expressions. The project of defining M-expressions
precisely and compiling them or at least translating them into
S-expressions was neither finalized nor explicitly abandoned. It just
receded into the indefinite future, and a new generation of programmers
appeared who preferred internal notation to any FORTRAN-like or
ALGOL-like notation that could be devised.
--McCarthy, John. "History of LISP." In Wexelblat, Richard L. (ed.),
Preprints of the ACM SIGPLAN History of Programming Languages Conference.
ACM SIGPLAN Notices 13, 8 (August 1978), 215-224. Also published in
Wexelblat, Richard L. (ed.), History of Programming Languages.
ACM Monograph Series. Academic Press (New York, 1981), 173-197.
So: (a) brackets were not used because they weren't on the keyboard
of the IBM 026 keypunch used to 80-column punch cards in those days,
and (b) the use of parenthesized S-expressions as a program notation
was something of an accident.
Here is the factorial function written in M-notation and the
now familiar S-notation:
fact[n] = [ n = 0 -> 1; T -> n*fact[n-1]]
(define fact (n) (cond ((= n 0) 1) (t (* n (fact (- n 1))))))
and here is the list-union function in both forms:
union[x;y] = [null[x] -> y;
member[car[x];y] -> union[cdr[x];y];
T -> cons[car[x];union[cdr[x];y]]]
(define union (x y)
(cond ((null x) y)
((member (car x) y) (union (cdr x) y))
(t (cons (car x) (union (cdr x) y)))))
Keep in mind that M-notation used an actual rightarrow character, not
the two-character digraph "->" that I have used here to approximate it.
--Guy