SICP in Python
www-inst.eecs.berkeley.edu
www-inst.eecs.berkeley.edu
It is a perfect example of Rich Hickey's "Simple made easy" talk from a few days ago.
In comparison, Python has way too much cruft.
We actually went through tons of different programming paradigms that scheme and lisp probably weren't really designed for, like OO (closures upon closures, all the way down). Throughout the class harvey and the TA's emphasized that everything we were learning could be done in any language, and didn't actually require scheme or lisp (yes, we never got to macros).
I can understand why you it might seem strange to port SICP over to scheme if you read SICP with the intention of learning lisp, but at berkeley the point of using SICP was to iterate through many different programming paradigms and cover basic computer science. unless they've found a better manual for this, it makes a lot of sense to just translate SICP instead of starting from scratch.
I think the language was only irrelevant because Scheme is so simple. We covered it in a couple of lectures and then it stayed in the background.
I really don't see the case for switching to Python at all--why "fix" something that isn't broken? Everybody seems to just assume that Python is a better choice.
That said, I think scheme is one of, if not, the best language to begin programming in, and agree with you that none of the reasons given for switching were very compelling.
Those scheme handles OO paradigms, the way it does is kind of annoying below the abstraction. however, scheme wasn't designed to handle OO, it was designed for functional programming. if i remember correctly, mutability is a hacked on addition (one of the reasons you use set! instead of def).
That said, the self-paced class seems really good. Some of my friends are TAing for that class and it seems to be going well.
It was a little easier back in the 80s when the new students would only have known BASIC or 6502 assembler
i think scheme is still great if you already know some programming because you can appreciate it even more.
My understanding was that MIT switched to python because in later courses they could actually use it to get things done (robotics, image proc, etc). While if they taught scheme they had to at the end of the course pretty much say: well that was fun, now we have to teach you something useful to get the rest of the course done.
mit and berkeley had/have the exact same "problem" with scheme (ie they don't/can't use it in any other class except the intro-to-into-cs class). This usually resulted in upped div classes spending a a class or two (basically a week of instruction, or a week of lab) on teaching the basics of the language the course is in. Though when i took the compilers course a few semesters later, the second slide of the entire course was "RTFM", and the professor dryly noted that we would be compiling a subset of python down to x86 assembler using c++, and despite the fact that he didn't expect any of us to know those languages at all, we didn't have the time to spend a lecture or discussion/lab on learning them, so we would have to learn them, on our own time.
I suppose that switching to a language that can be used in many classes is nice, but i don't think the students should have that much trouble switching if the professors supply supplementary material and they (students) understand the intro courses well enough. Plus, I think it's a good idea to get exposed to as many languages as possible, so you learn to think in a way that you can code well in any language.
The way the Berkeley intro course series is structured, it actually makes sense to not teach the fifth chapter in the first class: the idea is that you go from the top down, starting with really high abstractions and working your way down to building a computer out of logic gates. The fifth chapter fits in with the latter portion more than with the rest of SICP.
Also, MIT doesn't teach SICP at all in its intro course any more, as far as I know. They've also switched to Python, but I don't think they've kept the book, structure or material from the Scheme course (unlike what Berkeley is doing here).
I've never been involved in teaching CS or programming, and while I really do think SICP should be required reading for all CS students (and for all programmers) just because it's so good, I respect that teaching is very challenging, and fitting it all into a single semester might be tough. There are some very smart and experienced people who have spent a lot of time thinking about this (see "The Structure and Interpretation of the Computer Science Curriculum"), and I hesitate to put SICP on a pedestal where it can't be touched.
As I said, hopefully some (or many!) of the students taking this class at Berkley will be curious about the original book and will seek it out on their own.
I also don't think SICP is perfect; however, I think it inherently much better than anything--even itself--done in Python simply because Python basically forces less breadth. I recently read an interesting paper[1] that I think could lead to an even better class; if you're interested in this sort of thing, it's worth checking out.
[1]: http://www.sics.se/~seif/Publications/fdp.pdf
It's also not really designed for a completely introductory class, but I hope that most of the people coming into Berkeley CS aren't completely unprepared.
On a slightly unrelated note, a completely different approach to an intro class could be cool too: instead of focusing on learning, maybe the first semester should be dedicated to just building something cool on a computer and letting the learning happen naturally. The more formal classes can always come later. For something like that, I could see using Python--although it wouldn't be my first choice by far--but that's a completely different story.
Looking through the later lecture titles, it's quite clear that (despite what other commenters are saying) the "deeper" parts of the course have been preserved.
There's a bit that's been lost in translation; in particular, while the emphasis on metalinguistic abstraction has been kept (students are going to be implementing an object-class system, in a rather elegant way that uses Python's capability to redefine attribute getters) the more exotic models of computation pursued in the old 61A have been abandoned. No more ambiguous evaluator. This is perhaps inevitable - it's just impractical to create a metacircular evaluator for a language as complex as Python. Still, the core of the class has remained, which is a testament to the fundamental similarity of the the Lisp model of computation with that of many modern scripting languages.
All the same, I'm thrilled that SICP is being taught.
However, they still use SICP behind the scenes because they have a bunch of lecture notes for it, and because it really is a great book.
btw, i don't think harvey actually retires until 2013 or 14. i think he's just doing behind the scenes stuff now.
What is important are the big ideas. For example, the course covers several paradigms: functional, oo and logic programming. The book uses Scheme for the first two and a language with very Scheme-like syntax for the last; Python is completely unsuitable for all but oop, and even there is too complex compared to Scheme.
I took this course in its old iteration last year, and it was a brilliant course, probably the single best course I've taken on any topic. That was partly because of the professor, who has retired, and partly because of the book and language. Now that only the book is the same, I suspect the course is very far from brilliant.
I should amend this by saying that the professor, who is actually from Google, is probably good--he created a set of AI projects used in a bunch of AI classes that are very good. However, the previous professor was particularly good as a professor--his research involved CS education. So far, he has been the best professor I've had, and I've had some very good ones.
> What is important are the big ideas.
Go back and read section 1.2 ("Procedures and the processes they generate") again. As far as its authors are concerned, this is one of the big ideas. Basic concepts of time and space complexity and recursive vs. iterative processes are so important that they appear as soon as the basics of Scheme have been introduced. It's a core theme of the book (Why is this n-queens program slow? How can we eliminate two extra stack saves in this register machine program?), and the main questions in chapter 5 that the evaluators in chapter 4 don't answer fully (but look closely at the CPS evaluator in section 4.3) are "how do procedures return values to their callers?" and the related "how can we write an evaluator that doesn't grow the stack when executing tail-recursive procedures?"
Ultimately, the beauty of SICP isn't in the paradigms covered but the understanding of how programs execute, and the beauty of Scheme is the simpleness of its control flow . It's far easier to a understand Scheme program than one written in Python, Haskell, Prolog, or any other high-level language. Do most people understand (modulo sophisticated optimizations) how the Python interpreter actually handles, say, comprehensions, iterators, generators, or its complex object-oriented features? Can a first-year student add these features by hand (forgetting completely about macros and first-class continuations) to an interpreter herself?
It amazes me that Berkeley professors don't want to teach Scheme (and worries me, as they're much cleverer than me). The whole magic of the language is that in the end there isn't any magic at all.
I've talked with him about this choice and he has a lot of sound reasons for making this move backed by his years of experience teaching in various languages.
What's your line of thought? I use Clojure many hours every day and while I think that LISP languages are awesome, I don't think they're a good choice for a 1st programming course either.
The best time to learn about different paradigms is right when you're starting out; if you basically only learn how to program imperatively, you're liable to start believing that that's the only way to go. I know because this happened to me (I was self-taught and learned a different set of languages, but it had the same effect); ultimately it took me longer to come to and start using functional programming properly than it would have had I learned about it at the very beginning.
I can confirm that moving to Python was a very well-reasoned decision. Having TA'd the Scheme version of the same course 2 or 3 times, I can say that for all talk of Scheme having very simple syntax, it's surprisingly hard for students to get used to.
- The code is hard to read, and, a humans, we're not built for nested expressions.
- Useful data structures, like key-value stores, and indexable lists, are limited, or introduced late
- Having recursion thrown at you in week 1, before you've learned basic debugging, the concept of abstraction, or how to write readable code, gets in the way of learning to program.
- Almost nobody uses scheme.
That might be your value. But, the goal of SICP class is not to teach functional programming or create fpfs.
What's an fpfs?
In [2] the solution given by yairchu can be written succinctly via generators, which look extremely like a mathematical set definition.
def grandKids(generation, kidsFunc, val):
return reduce(lambda a, v: (x for v in a for x in kidsFunc(v)), xrange(generation), [val])
I often happen to think about a problem and explicit it with pen and paper using pure mathematical set notation then implement it in Python.[1] http://stackoverflow.com/questions/1017621/why-isnt-python-v... [2] http://stackoverflow.com/questions/1016997/generate-from-gen...
What you have done there is cute and commendable as a mental exercise, but if i'd ever encounter that in production code someone would make a close encounter with my chainsaw. This is basically undebuggable (i don't know the line/statement debuggers python has available, so i'm guessing here at what happens) because either the debugger will step over that in one step because it's one statement, or it'll just keep stepping on the same line again and again which is also entirely useless.
Lastly, what you did there is basically golf the living hell out of that code to bring it down from multiple statement lines to a single one. If i have to reach to such means i might as well use Perl. Only Perl actually does allow me to put multiple statement subs into a lambda, so i don't have to golf there.
Weird days when i have to golf in Python but don't need to in Perl.
http://wla.berkeley.edu/~cs61a/fa11/projects/trends/trends.h...
metacircular Scheme interpreter
lazily-evaluated Scheme interpreter
non-deterministic Scheme interpreter
pseudo-Prolog in Scheme
register machine simulator
compiler to bytecode for the same machine
edited for formattingWe didn't do the registers and bytecode, which was too bad although fair to students taking the class with less programming experience. One happy side-effect of the switch to Python is that there is now a self-paced version that allows the students to do all that if they want.
The lazy interpreter was also brilliant--realizing that you can change a language's behavior drastically with a small change in the interpreter is very empowering. Coincidentally, that's what pushed me over the edge to learning Haskell, so I'm extra grateful there.
Overall, the amount of magic that class showed me definitely made it worthy of the wizard on the cover.
I took this class while it was still taught in Scheme, and I loved it. Now I'm teaching it in Python. I am also sad to see Scheme go, but I think we gained as much as we have lost in our switch to Python. For example, I argue that Python dictionaries are more intuitive to use than the old "association lists" implementation in Scheme (we still taught the implementation). Concepts like MapReduce and concurrency that we cover later on in the course are also cleaner and more elegant than the Scheme implementation. The above-the-line OO syntax is also much, much easier to use.
We are still covering interpreters as our last unit. It will be for a "calculator" language, with conditionals and assignments. We are hoping to cover a lot of the same concepts, but we decided that a metacircular interpreter is obviously too difficult. We are keeping project 4 the same (Logo interpreter) but we have ported it to Python and wrote some new questions. Personally, I think the OO-centric interpreter is an improvement over the old Logo interpreter in Scheme (we can have Environment objects that now contain Frame objects, for example. Before, environments were just a list of association lists).
Having a statically typed language would add unnecessary complexity to the course; those languages come later anyhow.
Finally, some of the particularly brilliant insights that Scheme gives (code as data and an extremely elegant interpreter in Scheme) are absent in both Haskell and Erlang.
That said, we really should have more functional programming in other classes. I think CMU does this with ML throughout the CS program, and I envy them in that regard. However, this is a different issue; I don't think a language like that would fit any better to SICP than Python.