If not SICP, then what? Maybe HTDP?


Hard-core CS geeks worship at the altar of SICP, the acronym for the seminal Structure and Interpretation of Computer Programs by MIT's Harold Abelson, Gerald Jay Sussman and Julie Sussman, the functional-programming deep dive into Scheme and head-scratching problems that set the curriculum for "beginning" computer science and engineering students at the Massachusetts Institute of Technology from the 1980s onward.

While SICP (yes, everybody uses the acronym) is considered a holy grail for serious computer scientists, it's hella hard to figure out. For me, programming "methods" that make me jump through intellectual hoops made of mathematics make it hard for me to learn the actual programming.

Confession time: I have the same problem with Robert Sedgewick and Kevin Wayne's Computer Science (aka Introduction to Programming in Java). The examples the book presents and the problems it asks students/readers to solve involve a lot of thinking about the mathematical nature of the problem, and the nitty-gritty of making programs seems to fade into the background. That's why books like Y. Daniel Liang's Introduction to Java Programming seem to meet up with where I'm at in terms of learning programming.

But what about the lofty, Lisp-y ideals of SICP? Even MIT has moved on, and the school itself has a contingent offering and developing another Scheme/Lisp-driven textbook, How to Design Programs (read the latest edition for free, and get the print book from MIT Press).

So why the shift away from SICP? The professor-authors of How to Design Programs lay out their reasoning in this 2004 paper, The Structure and Interpretation of the Computer Science Curriculum.

Here is the abstract from the paper written by the HTDP author-professors (and yes, HTDP, sometimes HtDP, is the accepted shorthand; books with fervant fans get acronyms):

Twenty years ago Abelson and Sussman’s Structure and Interpretation of Computer Programs radically changed the intellectual landscape of introductory computing courses. Instead of teaching some currently fashionable programming language, it employed Scheme and functional programming to teach important ideas. Introductory courses based on the book showed up around the world and made Scheme and functional programming popular. Unfortunately, these courses quickly disappeared again due to shortcomings of the book and the whimsies of Scheme. Worse, the experiment left people with a bad impression of Scheme and functional programming in general. In this pearl, we propose an alternative role for functional programming in the first-year curriculum. Specifically, we present a framework for discussing the first-year curriculum and, based on it, the design rationale for our book and course, dubbed How to Design Programs. The approach emphasizes the systematic design of programs. Experience shows that it works extremely well as a preparation for a course on object-oriented programming.

The paper gets right into what we might want to call "the SICP problem" (slight deletions marked by ellipses serve to remove references to charts, and emphasis is mine):

More generally, SICP doesn’t state how to program and how to manage the design of a program. It leaves these things implicit and implies that students can discover a discipline of design and programming on their own. The course presents the various uses and roles of programming ideas with a series of examples. Some exercises then ask students to modify this code basis, requiring students to read and study code; others ask them to solve similar problems, which means they have to study the construction and to change it to the best of their abilities. In short, SICP students learn by copying and modifying code, which is barely an improvement over typical programming text books.

SICP’s second major problem concerns its selection of examples and exercises. All of these use complex domain knowledge. ... Some early sections and the last two chapters cover topics from computer science ...

While these topics are interesting to students who use computing in electrical engineering and to those who already have significant experience of programming and computing, they assume too much understanding from students who haven’t understood programming yet and they assume too much domain knowledge from any beginning student who needs to acquire program design skills. On the average, beginners are not interested in mathematics and electrical engineering, and they do not have ready access to the domain knowledge necessary for solving the domain problems. As a result, SICP students must spend a considerable effort on the domain knowledge and often end up confusing domain knowledge and program design knowledge. They may even come to the conclusion that programming is a shallow activity and that what truly matters is an understanding of domain knowledge. Similarly, many students lack an understanding of the role of compilers, logical models of program execution, and so on. While first-semester students should definitely find out about these ideas, they should do so in a context that reaffirms the program design lessons.

In summary, while SICP does an excellent job shifting the focus of the first course to challenging computer science topics, it fails to recognize the role of the first course in the overall curriculum. In particular, SICP’s implicit approach to program design ideas and its emphasis on complex domains obscures the goal of the first course as seen from the perspective of a typical four-year curriculum.

The HTDP professors want to make clear that the secret sauce is not Scheme, per se. They use a tuned subset of the language, something made possible by the Racket IDE (formerly DrSceme, now DrRacket):

Combining SICP with a GUI-based development environment for Scheme won’t work better than plain SICP. The two keys to our success were to tame Scheme into teaching languages that beginners can handle and to distill well-known functional principles of programming into generally applicable design recipes. Then we could show our colleagues that a combination of functional programming as a preparation for a course on object-oriented programming is an effective and indeed superior alternative to a year on just C++, Java, or a combination.

This is a deep topic, and I'm more concerned with figuring out the best way to learn programming concepts and practices without going too deep into the quirks of a single programming language, or hitting roadblocks in the form of scientific and mathematical concepts that are ancillary to the practice of programming itself.

Of course there's always the pull between the foundational approach favored by HTDP and maybe even in the "major" Java and C++ textbooks and college courses that use them, versus the practical approach of "here's how to make a program that actually does things ... learn these in-demand frameworks ..." and more urgently, "develop a foundation in JavaScript/Ruby/Clojure and go forward from there."