A brilliant CS educator named Matthias Felliasen (who is also one of the nicest guys in computing) and his colleagues have spent many years working on a teaching environment and curriculum for CS. The lynchpin of their program is (was? — honestly I haven't kept good track) something called TeachScheme, which is instruction in the Scheme programming language: a language with which I am reasonably familiar.
Felliasen wrote a response to Paul Lockhart's brilliant A Mathematician's Lament which, in a single anecdote, encapsulates for me why I don't think TeachScheme is the answer… Felliasen tells the story of an extremely bright student who "in tears" just couldn't figure out why the following Scheme fragment returns 0 on any input:
(define (f l)
(cond ((null? l) 0)
(else 1 + (f (cdr l)))))
After deciphering the parentheses (with minor help from some square parens omitted from the original because standard Scheme) one discovers that the real problem is that the student clearly meant to write
(define (f l)
(cond ((null? l) 0)
(else (+ 1 (f (cdr l))))))
which computes the length of an input list l
.
Now, it was obvious to me that the student's program shouldn't work. What was not obvious to me was why it doesn't fail!
The answer after some reflection is:
For simplicity (!), the else
body of a cond
can contain a sequence of expressions; the result is the value of the last expression.
For evaluation purposes, 1
and +
evaluate to themselves (a number and a function respectively); these evaluations are ignored.
Thus, this program is not erroneous in and of itself: it has a well-defined meaning and Scheme cannot reject it.
The end result of all this is that a simple mistake that any competent language and its implementation would easily have ruled out is allowed to proceed. By doing so, the language turns said simple mistake into a deep and difficult bug.
Is it surprising that a brilliant student would make such a simple mistake? No: I've been making it for years. Scheme throws out everything we were taught for 12+ years of mathematical syntax and semantics in favor of a syntax convenient for compilers. This is annoying, but it might be livable — except that using conventional syntax and semantics has really surprising results here.
In other words, Scheme is a language pre-built to punish a natural human mistake.
Keith Packard once suggested to me that any programming language that doesn't support standard infix arithmetic with proper unary minus and "computer MDAS" precedence is fundamentally broken. After many years of reflection, I have come to totally agree with him.
Syntax and redundancy are in programming languages for important reasons: they allow the language to more readily distinguish sense from nonsense at the earliest possible stage, and they try to ensure that when the meaning of a program construct is unclear to the author or reader, the language will reject the construct as valid at the earliest possible stage. The problem with parentheses and simple, naive evaluation in Scheme is not matching: it's that without visual cues it's really hard for our human brains, even as trained by our educational system, to figure out what the hell is going on.
Our Nickle programming language is designed according to principles that would catch the above mistake on several levels:
Nickle has a more helpful syntax that would keep this mistake from being made in the first place and would make it obvious if it were made.
Nickle tries to ensure that mistakes are caught and reported as early in program processing as feasible. In this case, Nickle would reject a program containing the mistake before ever evaluating it, making it much easier to find and fix.
Nickle has a static type system that would keep you from applying f
to a non-list thing. (Nickle doesn't have lists, but still…)
One place where I definitely agree with Felliasen is that it's all about what happens when the student makes a mistake. Where we disagree, I think, is that I think we should accept that even the best programmers make natural human mistakes constantly: any tool or curriculum for humans should minimize the ease of making mistakes and should maximize the consequences of those mistakes.
For every 100 failed TeachScheme students, I'm wagering 50 would succeed given a better first programming language. Right now I'm using Python, but I am tempted by ML, Haskell, Nickle, and even Pascal. All of these are far friendlier to newbies and experienced programmers alike than Scheme, while being just as suitable for teaching basic computing concepts.
So…yeah. I helped deal with some newbies who had been taught Intro CS in Scheme once, by one of the creators of Scheme. Count me out on this one. (B)