Why MIT Switched from Scheme to Python (2009)
wisdomandwonder.com
wisdomandwonder.com
What was great about Scheme (Lisp) is that most programs are basically words from your vocabulary, parentheses, and cars and cdrs. With procedural languages, there is always a sense that the language provides all the tools, and the magic happens somewhere underneath the hood. But with Scheme it feels as if it's happening right before you. It makes you feel like a wizard, and not a monkey. And it requires knowing all the spells. It requires knowing how to make magic happen. Or not. Once you know none of it's magic. But that's the point!
Python is arguably easier and more practical for both science and work. It's already popular on the web server, and is used everywhere else -- unlike Scheme.
But the recent resurgence of functional programming is super exciting with Elixir and Elm and the like.
I'm looking forward to building my next project using Elixir.
Here is the classic course: https://ocw.mit.edu/courses/electrical-engineering-and-compu...
Original video lecture on YouTube (linked from above): https://www.youtube.com/watch?v=2Op3QLzMgSY
My favorite section is where they go over making a constraint based system that will either calculate degrees F or degrees C. Or validate that the two given values are accurate. All depending on what you have entered. And this is done from the ground up. No hidden magic of the system has to support you, by and large. (Not strictly true, as this does make use of GC and such throughout.)
If you hadn't seen it, https://www.infoq.com/presentations/We-Really-Dont-Know-How-... is a great video showing Sussman's style. He also showcases a program they wrote that could solve circuits based on this general idea.
I wish that there was a camera pointing to the crowd when he said the more controversial things.
I didn't know that Sussman hired Stallman. Their work changed our lives.
By far the most rewarding class I've taken at MIT. Check out the psets, they're pretty fun.
1) Learning must be applied learning. Give people problems to solve and they will come to you for data structures and algorithms, O notation, etc. If they don't, they should do something else
2) A lot of what's out there in programming languages are cargo cults, and newbies need to be prepared for this. For instance, virtual function inheritance isn't a thing. It's a weird call chain pipeline system glued into your vtable, which C++/Java teaching also won't bother to tell you exists. Make people start from assembly, graduate to C, then write their OWN vtable, so it's demystified. Now you've reduced the ability of software designers to piss on your leg and tell you it's raining.
So ideally I'd want students (at first) to be doing something either close to the machine or in the functional model. As they say though, the imperative of 1) means getting people to actually produce something, which is easier in Python.
This is essentially what CS50 at Harvard does, and it seems to work well. Once a student has been exposed to these 3 languages, subsequent courses can explain how a computer works and introduce new paradigms (FP, LP).
Python is a fairly decent language for starting people off:
* It doesn't have a lot of boilerplate, so no magic "I'll teach you what this means in three weeks" steps
* Output for debugging is fairly easy, since print accepts a lot of stuff without needing to muck with formatting strings
* Assignment is a statement, not an expression. You can't say "if x = 3" by accident
* Python is one of the major programming languages, so you're teaching students something that is pretty much guaranteed to be useful for them.
Scheme levels the playing field. I have never encountered a student who entered university with years of functional programming experience and I was a TA for an introductory CS course. I think moving back to Scheme would be a wise choice for universities that are combating problems with diversity.
(I skipped the first two intro CS classes in college after talking to the professors and figuring out the right place to start given my background.)
One of my friends was able to skip 61a by meeting with the department chair, Paul Hilfinger, and convincing him that 61a would be a waste of time for him. My friend could drone on and on about the simplest of subjects so we assumed he just annoyed Hilfinger until he said "enough already".
In university, successfully challenging also gives you credits for that course (though there is a small fee per unit). I successfully challenged four courses (all in graphic design) - three of which were based on portfolio review and the fourth was based on completion of course projects in an accelerated period. Additionally, though not quite a challenge, I was able to speak with a couple CS professors and get them into admitting me into their courses despite not having the prerequisites (though was doing them concurrently).
The course requisite structure is more a guideline than a rigid computer system that works one way and only that way.
6.001 was a course in functional programming, based on the book Structure and Interpretation of Computer Programs.
6.01 (the replacement course that uses Python) is a project-based course involving robots and stuff.
Neither of these courses depend on any specific knowledge, but they would be very difficult courses if you've never programmed before. (Most people coming into MIT course 6 have programmed before.)
The "you don't know how to program, here's how to program" course has taken various forms over the years. When I was there it was 1.00, a Java course for engineers. Later it was 6.00, an optional intro to Python, based on "How To Think Like A Computer Scientist".
While I can't speak for MIT, SICP was used as the introductory course for CS in a number of universities. It assumes no programming. It is challenging, but that's the point of going to top universities.
When I want to university I never took a CS class before and nevertheless could program really well. I believe one is not able to go to a university if one is not able to teach oneself the prerequirements of the subject that one want to study.
Luckily the introductory course was based on SICP - and it really realigned my BASIC- and C- damaged brain.
It turned out to be the only course that I enjoyed so I eventually switched to a more computer systems and sciences oriented education.
It was a good introductory course for me, and perhaps most others. Perhaps not good for the most daft though...
I guess you also need some assembler-skills but it's hard in a totally different dimension somehow.
There's time for them to learn the details, but just learning that the functionality exists and knowing how to use it is a good start.
So, virtual functions aren't real because they're just vtables implemented in C. But C isn't real because it's just fancy assembly language. But assembly language isn't real because it's just fancy machine language. But machine language isn't real because it's just 0's and 1's zipping around the hardware. So I have to learn how integrated circuits work before learning how to program? No.
Bottom-up knowledge is important for understanding performance and other trade-offs. However, there's also a lot of benefit in learning how to program in a formal system without knowing much about how that system is implemented under the covers. If I was teaching an intro programming course to undergrads in 2017, I'd be strongly inclined to teach them a clean functional language first (e.g. Elixir, F#, etc.), and only introduce gory details like pointers and memory allocation later on.
I took a couple classes in college that were designed to teach what is going on underneath the 1s and 0s of instruction sets. I didn't take the classes about how circuits work, but they existed, I had friends who took them, and I really wish I had as well.
Maybe this isn't required knowledge to do software engineering, but it's definitely useful knowledge. Why wouldn't we want to learn these things?
I'm sure it would be possible to produce a few excellent software developers doing the bottom up approach as well, starting with a course on hardware, then assembly and then going up the stack from there. I would have loved that approach personally, but it would probably turn the average CS student into an awful programmer.
Sure, start the freshman off with Python. Let them get their feet wet and see whether they even enjoy this dark art at all. Besides, knowing about the hardware before "Hello World" isn't very helpful.
After their intro class, you don't do bottom up or top down. You start at both ends and work your way in. You got your computer systems course which teaches C and a smattering of assembly and hardware and your algorithms and data structures class that can use an easier language like (python/scheme) to reduce the cognitive overhead to teach the material.
If the students are taking these at the same time and the professors coordinate to explain how they relate at the various levels, you get very balanced developers. (Assuming they do well in the classes!)
Inductive logic and the functional paradigm maps onto all of these. And allows for more diverse abstractions without lying either.
It kept the focus on the underlying principles (every programming language is a set of primitives, a means of combination and a means of abstraction; recursion; interpreters; etc) that were powerful enough to let you pick up any other language without getting bogged down in the details. An opinionated language like Python seems like the wrong choice to teach fundamental structure (it WAS Structure and Interpretation of Computer Programs), but if they aren't approaching it from that angle and are looking more at application development then that's probably ok.
You can pick up enough of any language or framework from the manual, and google/stackoverflow/o'reilly will give you fine points/quirks, but that fundamental base that allows you to look at ANY program in ANY language and be able to reduce it to first principles is (IMO) a necessary component of any computer scientist's toolkit and the best insurance against the continuous rise of packaged software that is continuously burning the short grass in most software development.
I remember reading somewhere that focusing on application development is like training blacksmiths: you end up with people skilled at specific techniques but extremely vulnerable to "industrial" software that replicates the techniques and eliminates the need for custom development.
There are not that many blacksmiths left, and the truth is in 50 years there won't be that many application developers left either.
I like your comment, but the crystal ball statement in the last sentence is a bit too much.
Perhaps there will be a threshold reached where suddenly that goes away. But I'm not holding my breath.
Having done the intro course in Scheme, I'd say it helped me understand functional programming far more than I ever could have with Python, and it opened me up to different ways of thinking.
Even though I never again used any Lisp variant, I'm still really glad I learned it and feel that what I learned using Lisp has informed my future decisions.
Brian Harvey explained the decision to switch here:
"But, as I keep saying, the choice of programming language isn't the main point. I get upset when students, even the students who like 61A, refer to it as "the Scheme course." It's not a course about Scheme! It's a course about programming paradigms. MIT, where SICP was written, no longer includes that course in its lower division core sequence, not because they wanted to change programming languages, but because they changed the entire sequence from courses organized around big groups of ideas to courses organized around application areas: first "let's build and program a robot" and then "let's build and program a cell phone." That's a brave and thoroughgoing attempt to, among other things, attract non-nerds to computer science. To say, as some people do here, "MIT switched from Scheme to Python" completely misses the point of what MIT did; nobody is proposing any change half as profound at Berkeley." [1]
That's Berkeley. Abelson and Sussman once got MIT to trademark "Nerd Pride".[1] MIT still keeps the trademark active. Here's a Nerd Pride button.[2]
[1] https://books.google.com/books?id=LJq0JhoElk8C&lpg=PA78&ots=... [2] http://www.computerhistory.org/collections/catalog/E1312
[2] http://www.computerhistory.org/collections/catalog/E1312
2. I think you are focusing too much on the use of the word "nerd" here. Harvey chose the use of that word, not MIT.
The common phrase was that you should be made to take 61A as your first class and as your last. You really dont fully comprehend it until you get wider exposure, but you need that initial exposure so your brain can begin to knit things together as you see them.
Meta-Circular Evaluator RIP. You will be missed.
I have been using Ruby, Java, Scala, Python, and Haskell mostly for years now. But just recently I started working on the 4th edition of my old Common Lisp book and some preparatory work on a new Scheme book. I have been enjoying the Lisp-way of bottom up interactive development a lot.
Both general approaches have value. When doing machine learning it is great to have the universe of useful libraries for Python but for green field work that is more algorithmic, doing bottom up development in languages like Scheme or Haskell is also great.
Think about trying to teach the meaning of "public class Foo { public static void main(String[] args) { ... }}" to a complete novice. Class-based design, inheritance, visibility, return types, arrays, etc. all right off the bat. It's too much.
Scheme and Python both are much better choices for this alone.
I would have a semester teaching several "toy" languages in different paradigms: perhaps some kind of lisp, some kind of prolog, and some procedural language, followed by a second semester where students choose the language they want to learn, and they learn it by themselves.
That, right there, is the reason why I end up using Python so often.
As dynamic languages go, Python is not the best for anything, but it's good enough for almost everything, and there's probably already a library implemented for it.
My theory: it was the first language to take a human factors approach to language design. Not the best, but the first. This design philosophy has the simple consequence that Python programs are by and large incredibly easy to read, understand, and modify, compared to its contemporaries. "Network effects" did the rest.
Learning Scheme as my first language scared me away from programming for years. Yes, solutions to problems were often elegant and puzzle-like, but accordingly, the tools and patterns often felt constrained and roundabout. For example, consider recursive patterns vs conventional looping patterns.
In that class I often felt I wasn't learning a 'real' production programming language, but rather a language designed to teach me programming concepts.
To that point, I think Python offers a much more robust and straight forward tool set, while also being friendly enough for the young developer to sink their teeth into.
However, in retrospect I was just a bratty kid, who was learning a lot of valuable fundamentals. I'd like to think some of those have stuck with me to this day, esp. as functional patterns have come into vogue.
"The wizard book" is a great read and I recently starting flipping through it again.
[1]: https://github.com/sarabander/sicp
[2]: http://sarabander.github.io/sicp/
I mean, one should be able to look at the assembler output of hello.c and have an idea of what's going on. Without that level of understanding, I'm not convinced using C over many other languages gain you much. It's still a lot simpler than eg. c++, though.
I'm thinking something like: http://pacman128.github.io/pcasm/ but rewritten from the ground up for x86_64.
That was a long semester.
I mean, just write a simple C program that reads in argv[1] and then loops from 1 to atoi(argv[1]) doing fizzbuzz. Then compile the program (without optimization) and look at the generated assembly. I just did that on an x86_64 using gcc, and the generated assembly is pretty straightforward and maps pretty well to the actual C code.
The only part that doesn't neatly map to the C code is the boilerplate call-stack stuff, (subq instructions on the rsp register, etc.). But everything else maps rather neatly. The library calls to printf, etc. are mapped to a simple call instruction. It demonstrates how closely C code maps to the actual assembly for these sort of simple programs, which is what actually matters in a pedagogical environment.
This compared to similar Python code, where the actual op codes being executed would be vastly more complicated and less obviously related to the actual "business logic" of the program - you'd have constant incref/decref'ing of objects (assuming CPython), byte code execution in the main ceval loop, hash table lookups for globals, etc. etc. The point is C code maps much better to what the hardware is actually doing. Your arguments to the contrary (talking about vectorized instructions and GPU) are really just being nitpicky. That stuff can be covered later in more advanced courses.
I have found advice like this to be a good sign that the speaker has a very limited understanding of how modern computers actually work.
http://cs61a.org/articles/about.html
The last time I used Scheme was in 61A. I like Scheme; it was elegant. I probably would have continued to use it but Instructional Computing had a bastardized variation. I'm pretty sure that students of 61A will continue to use Python since they're using Python 3.
https://github.com/nickbauman/sicp/blob/master/src/section2_...
I loved the process. Scales fell from my eyes. I didn't get this with Python, even though I love that language too.
> https://cemerick.com/2009/03/24/why-mit-now-uses-python-inst...
For example, here is SICP with examples using the JavaScript shovel: https://www.comp.nus.edu.sg/~cs1101s/sicp/
BTW, since this site isn't super mobile-friendly, I made a modible friendly version a while back: http://ivanistheone.github.io/SICPapp/ (only first two chapters)
The most important thing is for good engineers to understand both near-universal basic concepts and the low-level impact of data structures and algorithms (like branch mis-predictions / deep pipeline stalls, memory usage, latency, locality.)
https://www.joelonsoftware.com/2005/12/29/the-perils-of-java...
I ended up in IT and programming, and when I bumped into SICP I regretted the 10 years spent without having read it already.
Someone commented that it's the first and last book you should read at Uni, and I totally agree
That said, the rationale presented in the article is a really good one. Hm.
I think it would be doing a disservice to other students if they didn't switch. The rationale given was a great one actually. OOO is there for a reason. I do not like the idea that FP is the answer for everything.
I understand many students used Python, C++, etc. This was the case for me as well. I did not go to any lectures for the Introductory course. I spent my time wisely studying for other Engineering classes (in reality: I actually didn't do shit and did other activities). You should do the same too.
What I am trying to say is, just because you already know OOO because you took the initiative before University (which I think - and I am biased - is a good thing to do), does not mean everyone else has. University is about teaching a body of students, all of education revolves around the mean of this body of students. It is a sad fact, but no professor or department or University will give you the unique attention you deserve; this is why I would not suggest University for that purpose. I only did University to get a piece of paper. I learned most programming stuff on my own time, before going in.
Teaching OOO, an easier of the two (FP/OOO), is a good thing. And teaching it in Python.. is a great thing. Kudos to MIT
I think instead, it is a better idea to keep Python/OOO as first year and in second year start teaching FP in whatever language. Or perhaps teach them both in first year. I think we just need to realize that when we go to University/School, we will have to walk at the pace of the "mean" even if that requires having to run (to catch up) or crawl (to slow down). Sad reality.
Edit: I just noticed that if I press the post button twice, it makes two posts. I deleted the dupe.