Why MIT uses Python instead of Scheme for its undergraduate CS program (2009)
cemerick.com
cemerick.com
I read this as "the parents paying tuition wanted their kids to learn practical skills so they can make money".
I learned Scheme as a first language and I will be forever grateful for it.
[1] https://htdp.org/ [2] https://mitpress.mit.edu/sites/default/files/sicp/full-text/...
Previous discussion on HN about the second addition:
https://news.ycombinator.com/item?id=14932552
EDIT: I feel like it is not all-encompassing but it is a good start. It is definitely unique in the concepts that it covers.
That being said, I did respect the course and the language. I didn’t understand the science part of computer science before starting the minor and that course opened my eyes pretty wide (as did the Data Structures course). It really forces you to think and understand what you were doing, much less poking and prodding (different from trial and error) than what you could do with Python and its libraries. Plus there’s significantly less information out there on it in comparison. I wouldn’t bring parents into it, they have almost no influence on universities unless they are privately funding/donating.
But my god those parentheses...
This is exactly what I look back on so fondly. I already had a lifetime of fiddling with libraries and stack overflow ahead of me, exploring pure computation was a completely eye-opening experience.
And so my use of Racket is simply as a dilettante. And I LOVE it. I have a lot of imposter syndrome and not really grokking data structures the way CS people can tell you the tradeoffs and implementation details of a B-tree. But, I LOVE coding in Racket when I get the chance.
For me, it’s a language where I can jank-hack things together like Python, but having more fun. Wonder if that’s because I never had the fun of Racket sullied by also having to learn data structures and CS fundamentals at the same time?
I pity the MIT students that will waste so much of their intro course learning what is a vastly more complex language. There will be so many students that will struggle to learn python-specific topics that are irrelevant to learning the act of coding and may decide that CS and programming just aren't for them. Scheme is such a perfect language for this task because it puts so little between the student and the crucial experimentation phase that can instill a fascination/curiosity with programming. And now MIT students will miss out on that.
By this measure C should be a popular university intro language too, but it is famously unsuitable as a first language, at least according to academics.
Correct me if I'm wrong - I just went to an unrespected state school - but I would think that the MIT admissions filter selects for students who wouldn't particularly struggle with something as small as language idiosyncracies, especially in an introductory course.
I digressed a little. Point being: while I'm unsurprised that some % of people from a broader range of abilities couldn't get functions or iteration or inheritance or whathaveyou to stick, I'd be very surprised if ANY % of the culled-by-18 right end of the Bell curve couldn't grok both fundamental concepts and any relevant part of the standard documentation (on which we appear to be in agreement.)
I’m having flashbacks... Thanks for that ;)
Time complexity was my worst CS topic. At least, for implementing the most efficient system. I’m not an algorithms guy.
As someone who has been part of running intro courses using a variety of languages: While I like the Scheme path for various reasons, I do not recognize the effect you imagine at all from the students I've seen. That there are complex areas of Python is basically irrelevant for intro courses, the few pain points are really easy to explain and remember, and Python is great for the experimentation phase (the core is easy enough, the (standard) library ecosystem helps satisfying random interests and can generally also be used without being exposed to problematic parts of the language, REPL)
Now I am a polyglot, jumping through multiple languages all the time, be it Python/Java/Javascript, or occasionally flirtation with some languages that are foreign to my daily routine but necessary to get my job done.
I am not quite on board with you claim that Python is chosen for monetary benefits. To be a qualified programmer, there is so much more need to be learnt beyond Python. Python however, is a GREAT choice to overcome the initial fear of writing code in general, because it is more tolerant.
My actual first language is C, and before my college I have never done programming before. I have to say, looking back, learning C as my first language without fully understanding the modern computer architecture is a horrible experience: so many questions as to why things is what it is now, so many traps, crazy pointers, cryptic errors, nightmare segmentfault. Programming is just very frustrating experience to me that the time. Of course, later on, it all makes sense, even pointer seems like a great idea(you can't have more freedom than that), just that we need to put great efforts regulating the use of it to prevent irregular behaviors.
On the other hand, Python is a tolerant language, yet providing a pretty comprehensive sets of primitives to play and experiment with. Had I started with Python, I might not waste the initial year struggling and questioning myself whether I could program at all.
People often talk about how simple Python is, but many of them have either no experience with or no appreciation for Scheme. When they do have exposure to Scheme, it tends to be some ancient, primitive dialect like MIT Scheme rather than modern, full-featured scheme like Chicken, or Racket, or Guile -- so they look at Scheme as a toy language. I don't know how often I've heard comments along the lines of Scheme being a fine academic language but impractical for real work.
Python does have a little nice lispyness to it, but it's deliberately limited by the language designers, the syntax is lacking and it has many frustrating inconsistencies and gotchas. Programming in Scheme is just so much easier.
Want to learn how a computer works? Learn C.
Want to study abstract comp-sci concepts? Learn Scheme.
Want to wire together libraries to get something running in the messy real world? Learn Python (or something similiar).
A well-rounded CS education really ought to include all of these to at least some degree.
Regarding Python vs. Scheme, I like both languages. I tend to prefer Python for certain types of programming, like NLP, machine learning, and math, just because the available libraries are so good. Having said that, I feel that the functional paradigm is superior to procedural programming and definitely (for me anyway) better than OOP, so for everything else I'd choose Scheme or some other functional language, like Elixir, Elm, Haskell, or Erlang, depending on my mood and what I'm doing.
the school I went used to teach C, Python and Scheme in the first year (nowadays it's C, Python and Racket). I don't think I remember more than one or two people actually liking the LISP experience, how bad it was when comparing to other languages is actually a common joke subject amongst alumni.
It is however pretty easy to implement something like racket's for loops on scheme using lower level macros, and there are some available.
Implementing something like common lisps iter is actually not very hard, and even improving upon racket's for loops is far from complex.
I believe that Scheme's DO is looping.
Functional programming of course maps (heh) very cleanly to this line of thought.
But most people hate maths and this way of thinking. In contrast, you get first year students "re-discovering" OOP ever year - for instance a common trick to make them learn design patterns is just to put a problem that calls for it in front of them, and three times out of four in my experience they will even come up with a pattern name close to the original ones.
A lot of the time when you meet someone who had a bad experience with Lisp, if you interview them a bit, you soon discover it was actually Scheme.
Scheme twenty years ago, R5RS was even worse than now. It had nothing practical in the spec. No way to write a program consisting of multiple files. No error handling. R5RS talks about situations that trigger an "error", but nothing about how such a thing can be handled and recovered. Or how an error can be generated on purpose and then caught.
Anyone who studied R5RS in school was learning an utter piece of academic garbage; a serious regression from real Lisp.
The issue with the line of reasoning that “X language is bad because it was bad during an intro programming class” is that your experiences in that class do not generalize well. Sure, python might be better for writing some basic algorithm that you fully understand before writing a single line of code, and for fairly small codebases. However, try writing a large codebase and you’ll realize that, for example, managing state is really hard.
Sure, racket and other functional languages might require a greater learning curve than other languages, and of course they’re not the language of choice for performance critical applications (nor will Matthias Felleisen claim it is). However, as a systems developer who uses almost exclusively C++, I would argue that starting out with a language that forces you to think about your contracts, mutability, scope, etc, invariable create a better programmer down the line
Oh, and the deluge of useless parenthesis that it is, it hurts my eyes to read that code.
Nobody ever said most list operations is anything else than o(n), and if you are using lists you are probably using the wrong data structure. Vectors or hash tables would probably be a better choice (which are provided by all serious schemes).
Oh, how I wish I could share the joy I experience using Paredit with those parentheses. Paredit turns parentheses from an inconvenience into a turbo button for modifying code at an entirely new level of abstraction.
When you started coding, you probably used an editor that worked on units that were single characters. Think Notepad. Then maybe you learned a programmers editor like Emacs, Vim, or Atom or Sublime. There you learned to cut, copy, fold, spindle, and mutilate code in lines or paragraphs.
But Paredit... oh Paredit... now you have the tools to work with your code not in characters, lines, or paragraphs, but in code forms—the same stuff your code is made from.
And the best part is that Paredit doesn’t have to have a deep knowledge of your code, groping imperfectly like Intellisense. Paredit is deterministic and easy to implement.
If I could have an S-expression based version of every other language simply for paredit, I'd take it.
Now a story for a different day is how much I hate typing commas in non-lisps.
I did. Actually, when I found Python (some 20 years ago), I thought - "Here's it - Lisp for real world".
I can see it. I used to make a lot of money doing Python programming. About $40k a year more than I ever made doing C, Java, C# or C++. Of course, I did Python more recently, so there is the wage inflation between 1992 and today to consider. Still, you can make a lot writing Python code.
Also, some languages and applications require a higher degree of knowledge, training, and expertise than others. For example, I would expect to pay a programmer working in robotics more than I'd expect to pay a React or Angular developer.
Having grown up working in construction, I completely agree with your tool analogy though (and used the same analogy in another comment).
@gronne - About three times that, but close. ;)
Of course, some tools maybe more effective than others, but I still find sad measure in money terms any of them...
I vaguely recall one of the recent updates removed that limitation, but could be wrong about that.
But we highly overvalue which formative experiences matter. If I were to get into a time machine, go into your past, remove Scheme and swap in some other language, you'd probably be grateful today for whatever that other language was. It just hit you at the right time, like whatever song was on the radio when you first fell in love.
Every step on our path is dear to us because it got us where we are today, but there are many many paths and little reason to want others to follow in our footsteps. If anything, we should discourage that because the world doesn't need another me or you. It's already got those.
Python is a real language that does real things, but it's also completely approachable to a newbie.
If programming seems hard, then you have a bad teacher that is probably just trying to evangelize their hobby to you.
And god help anybody that tries to start with JavaScript.
JS is a good starting language, for the typical starting student, because it helps them cultivate their intrinsic motivation.
Less importantly, but still important to me: JS is also a more beautiful language than most mainstream languages, except for the ten or fifteen god-awful warts that it admittedly has, that everyone is disproportionately obsessed with.
(I, unlike most of my students, was interested in computational thinking from the very beginning: iteration, recursion, data types, algorithms, etc, and I was uninterested in actually making things. My first languages were BASIC and Pascal and C, and as far as I can tell, that worked out okay.)
For instance: brush your teeth, then put on your clothes, then get in the car, then start it.
The "JavaScript" way to do this is that starting your car is somehow nested inside of the brush your teeth event. Everything is a callback of everything else, so trying to explain to your computer what you want it to do ends up as a giant spaghetti mess.
Obviously there is a JavaScript way of thinking that allows you to think of brushing your teeth as a dependency to starting your car, but I don't think that this is how most humans think by default, so it's a terrible way to teach students.
It makes them think that computers are these complicated things that take some immense skill to operate, but they're not anymore. You just need to tell the machine what to do, and good languages like python make that really easy.
At this point in my life, I'm mostly writing C++, JavaScript, and golang, but I'm extremely thankful that I started with python. When I need to bang out a prototype, or test something in code, it is always my go to.
function first(cb) {
console.log('first');
cb();
}
function second() {
console.log('second');
}
first(second);
can now be expressed as new Promise().then(console.log('first'))
.then(console.log('second');
or async function first() {
console.log('first');
}
async function second() {
console.log('second');
}
async () => {
await first();
await second();
}();
depending on exactly what your goals are. The inversion of order ("callback hell") can be avoided if you stick to modern concepts. print "first"
print "second"
I mean...imagine explaining your example to somebody. That's difficult for some programmers to fully understand. import asyncio
async def first():
print("first")
async def second():
print("second")
async def _():
await first()
await second()
asyncio.run(_())
prior to python3.7, python didn't have similarly clean asynchronous programming tools. With python 3.5+, you could use the old event loop syntax [1] to do it, and prior to that, you needed to use `yield` and `yield from` for similar semantics.If you want synchronous stuff in JS, this suffices:
console.log('first');
console.log('second');
EDIT:The problem that JS had (prior to promises in ES5) was that the only way to do deferred/asynchronous things (like "run this after I get data from a network call") was to provide a callback, something like
function(resource_url, callback) {
data = get(resource_url);
callback(data);
}
This gets very trick very fast if you want to have chained calls (imagine that `callback` also conditionally requests a resource, and you want to do something with that resource, and based on that you may want to redraw the DOM and then...).There wasn't a good pattern for describing that in JS. The "common" pattern was to just have callbacks within callbacks, and unlike in python you'd often use anonymous functions, so you end up with nested anonymous functions which inverts the way you think, it's really hard to grok.
Promises and async/await linearize that, but that's a problem that python never really had to address because up until very recently, python didn't get used for async stuff.
[1]: https://docs.python.org/3.6/library/asyncio-task.html#exampl...
I say wedged because IMHO programming env's are the easiest to setup and maintain in POSIX OS's. This closed source OS I'm most in (because I stream simulations & games on this DAW) is not really suited for it.
One of the 1st languages I installed was python. For me the reason is a nice Raspberry PI I got from a friend of mine, but most of all the accessability of the language on literally all OS's you can throw a stick at.
Another reason is
python -v -m SimpleHTTPServer 8088
amazing, when you run it in verbose modeFor context, MIT's previous EECS curriculum began with 4 required courses for all EE and CS majors. This meant that EEs had to suffer through Scheme, and CS'ers had to suffer through circuits. I'm sure everyone has their own opinion on whether this is a good thing or a bad thing.
Regardless, the EECS department switched to a new 7(?) "core" class format in which students choose 4(?), giving students the freedom to take more relevant courses to their interests/major. In this switch, 6.001 (scheme) was out and replaced with a more hands-on robotics-based Python lab class.
I can't really say which approach is better, but I do think there's an important place for the more pure "thinking" computer science classes too, even if it's not the first class taught to freshmen.
The near-total demise of Athena matters here too. I can and do hire people with all those skills! It’s still very possible to get them at MIT. It’s just not nearly the default, and since it’s way up in electives I’m at least as likely to find the best people carrying a degree that says 21W as VI-3.
I don’t envy the VI admins. They have a problem akin to that of a suddenly virally successful startup. 400 people a year come in; about that many better succeed.
I remembered catch phrases like 'assignment is bad', only to be led down the 'functional programming' cult years later because it reminded me of sicp.
Building up entire systems from first principles is quite beautiful and illuminating - once you've used existing systems and began to wonder how they came to be.
For most people - I don't think they're really that curious. University is not structured to give you the time to go deep or be curious - you're busy doing assignments, readings and studying for tests. SICP is a gem for those who are lucky to have a few months to really go down the rabbit hole. For everyone else, it'll likely feel like needless torture or 'wow, that's cool and I don't have time to explore it any further' at best.
That statement, while true, should anguish the heart of anybody in any way related to or concerned for academia.
You do, however, get that time when you write a master's thesis.
Python3 (which I live in btw) doesn't exactly exude it's functional elements beyond the simple lamda you have to import from functools so recursive solutions don't lend themselves to it syntactically speaking, inherently in the language.
OTOH those battering rams come in handy for beating simple problems into submission.
I think there's basically only three ways to teach EECS: stack top-down, bottom-up or as-needed/random.
If students learned bottom-up, starting at silicon, they'd have a firm grasp, and be more mindful, of practical system capabilities. Python and such would either be a starting crutch or a last learned.
Just like Scheme, a learning language, we had a learning OS: MINIX 2. Such constrained environments are easier to teach but less relevant in the real world, but the valuable part is the mastery of concepts is portable across technological fashions... it instills a confidence that playing with the Linux or FreeBSD kernel doesn't because it's so overwhelming to all novices, rather unlike a minimal working example.
Furthermore, because of the bifurcations in tech, fewer people have even seen a server much less racked a datacenter floor up, or understand assembly or C. This is concerning if academia is mostly producing CS students narrowly focused on web FE/BE.
I don't know about Python, but that is one of the delights of SICP and scheme in general.
It's not that there isn't a OO implementation in scheme; it's that there are too many. Implementing an OO system is a medium-advanced exercise left to the reader. As a result there are many available, up to the point one wonders if "OO" can be rightfully coined "a paradigm".
Constraint based/logic programming? I think it's a chapter in SICP, and covered by one of the SICP video lectures showing how to build a simple prolog-like language to illustrate some other concept
Type systems? This one is a little funny. There's a SICP lecture on it (the recordings are from the 80s), and I thought it was an unfortunate choice of name, since "type systems" are a real and important concept now in modern computer languages and the naming would clash, but no, it actually was an implementation of a type system as we now use the term.
I think one of the reasons scheme doesn't have "a lot of stuff" is because most stuff, if well understood, is trivial. If it doesn't seem trivial, one simply doesn't have a deep enough understanding of the concepts yet.
One of the things about using scheme effectively as a teaching language is that it puts the wizardry in the actual wizard, not in the magic box with the blinkenlights.
Or, replace Javascript with any other high level language likely to be running on every smartphone. If there are competing offhanded suggestions then bonus lazy points for using a random number generator to decide the winner.
Only when the committee meeting is over do Lazy U. profs begin planning how to teach their classes. And there's more time for that since the Lazy U. committee meeting was an order of magnitude shorter than most. (Although the laziness would probably be recursive and result in the elimination of the lecture, lab, geographic proximity to students, and assignments that can be distinguished from publicly accessible repositories full of code and research.)
I regularly see others write Python code that I have to fix to add robustness. I also run "pylint" or equivalent tools before committing major changes to scripts because it is quite easy to make mistakes that won’t otherwise be found right away.
Some of my least favorite pitfalls:
- If you call a function that happens to refer to a variable that only exists in the calling code, it will work (and yes, since the same function can be called from more than one place, “caller” is not always the same so the effect is not always the same). Bonus points if it only matches the caller because of a typo. Any convenience afforded by this behavior is not worth the potential for head-scratching and painful debugging.
- Python has things that “seem” like the obvious/right thing to do when they are not. One great example is "except:", which to this day I have to keep correcting in various scripts to prevent important errors from being completely lost. Another one is expecting to write the entire script at column 0, when people are supposed to know 'if __name__ == "__main__"'. Also, a type’s apparent shared/unique status is not always clear so novices can get a long way with sort-of working code until they are completely confused by the broken cases (e.g. you can simply list and “initialize” class fields with trivial string and number values until one day you add something like a "dict()" and everything breaks for that one field because all your class instances are mysteriously sharing it; suddenly you need to define a whole new "__init__()" to fix things when it wasn’t apparently needed previously).
- It is not always obvious to maintainers of functions that keyword arguments are extremely fragile and that they can overlap with other arguments. If an argument is renamed or relocated for example, stuff elsewhere can break in stupid ways. Tiny code changes can create big headaches.
Could you give an example of what you mean by this?
def foo():
return bar
if ...:
bar = 42
print(foo())
else:
print(foo())
If ... evaluates to a truthy value, bar will be defined and foo() will return 42, if it is falsy, bar will not be defined and the code will throw a NameError.I would agree that this is extremely confusing behaviour. Of course people wouldn't write code like this (hopefully), but a similar situation might occur in a much more obscure situation.
This is not true. This code gives a NameError instead of printing "1":
def f1():
print(var)
def f2():
var = 1
f1()
f2()
If it can't find a name in the local scope, it will look in enclosing functions, then the module scope, then the builtins. But it will never look inside the caller's scope unless the function is defined in the caller's scope.Python's implicit scoping can be confusing, but it's not quite that bad.
These tools were designed to be accessible to non-programmers and had our entire cross-disciplinary class making games, interacting with hardware, and getting inspired to find new ways to interact with computers. I wish this class had been required by every first-year CSE student.
I went to one lab, the lab computers and all campus computers were running Slackware with Afterstep. I was a Window Maker and Red Hat user at the time, I was impressed and thought it was neat.
Of course this is from memory and 18 years ago almost to the day, but that's the gist of it. Anyway, I felt like I learned a ton and loved it every bit. I went to a few of the CS club meetings and got the impression basically every one had already had internships with Intel, IBM, or Microsoft. This was my freshmen year and was basically in awe.
Oh how I bloody want to do jut this today. I want my program to be split into as small parts as possible, every part (i.e. every function) being defined in a separate file. But Python encourages the direct opposite - writing long files of code to avoid introducing too many "modules" and this is a debilitating headache.
> At some point along the way (he may have referred to the 1990’s specifically), the systems that were being built and the libraries and components that one had available to build systems were so large, that it was impossible for any one programmer to be aware of all of the individual pieces, never mind understand them.
Thanks to my ADHD it is very hard to me to fit anything that doesn't fit in half a screen into my mind. The longer a module growth the lower my productivity falls.
How does Python encourage mega-files? AFAIK there's nothing that prevents nor discourages proper organization of code into files.
I frequently use multiple files to organize my library implementations.
I think most would consider this a good thing. WYSIWYG. If a class is so gargantuan as to require multiple files, it should probably be multiple classes that communicate via a well defined, public API, not implicitly.
>You have to invent names all the time, a package, a module and a function having the same name smells a headache.
This is only an issue if you are importing *. If you import in a namespace (`from foo import module`, `from bar import other_module`), you can have `module.module`, `other_module.module` and anything else all living in harmony. If you work in python as python intends and not C/C++ (namespaced imports, not text-prepended ones), it's much, much cleaner.
It's also possible to, generally speaking, have private submodules within one larger module. You can do this with `__init__.py` by importing the various submodules, explicitly re-exporting the things you wish to be top-level public, and setting `__all__` to include them. This is why I can do something like `import numpy as np; np.ndarray` even though ndarray is defined in an extension module referenced by `numpy.core.multiarray`.
See multiarray (https://github.com/numpy/numpy/blob/master/numpy/core/multia...), which pulls things from `numpy.core._multiarray_umath`, then exported by core via `numeric` (https://github.com/numpy/numpy/blob/master/numpy/core/__init...), then again by the top level __init__ (https://github.com/numpy/numpy/blob/master/numpy/__init__.py...).
IMHO anything that doesn't fit in one screen is "gargantuan"
> If you import in a namespace (`from foo import module`, `from bar import other_module`), you can have `module.module`, `other_module.module`
Which looks ugly and feels a nasty headache if you want to maintain intuitive vision of your code and dependencies structure.
> It's also possible to, generally speaking, have private submodules within one larger module. You can do this with `__init__.py` by importing the various submodules, explicitly re-exporting
I know but even reading this paragraph hurts. Too much mess to manage manually.
This is a bit of an odd definition, but sure (I've seen C++ files whose imports alone were gargantuan under your definition). I just looked through a production python application, and it there were 2 non-test classes that were more than 100 lines long. Both were relatively verbose (well commented, use type hints so argument lists use significant vertical space, etc.)
In general, it seems like you're limiting yourself to, with the necessary boilerplate, one or two functions in any file that isn't "gargantuan". This makes it needlessly difficult to understand the structure of your applications since you are forced to split related logic up among multiple files. This, more than screen length or the import syntax, makes it much, much harder to "maintain intuitive vision of code and dependencies structure" as you say.
>Which looks ugly and feels a nasty headache if you want to maintain intuitive vision of your code and dependencies structure.
Not at all. It's more explicit about the dependency structure (`module.method(args)` at a call site gives you a much better idea of the structure than just `method(args)`), and so makes it significantly easier to maintain an intuitive vision of the code and dependencies.
It's incalculably easier to understand dependency structure when using the `import module` syntax than `from module import Class` or `from module import *`. So much so that the former allows reliable, large scale refactorings without any runtime information. The others, as you correctly recognize, do not.
>I know but even reading this paragraph hurts. Too much mess to manage manually.
Then don't! You don't need to. It's really only necessary for truly public/widely used APIs (like numpy) where understanding the internal structure of the module is not worth it for the average user.
I mean for the library developer, not for the user.
This doesn't mean assembler or brainfuck is okay as a first language (although the former was the 2nd langauge I taught myself and its reputation for difficulty is vastly exaggerated in my opinion), but it does mean that endless discussions about whether Python is better than Javascript or C is better than Lisp is probably splitting hairs.
I'm not so sure.
Here's an example of blinking an led with Lisp:
http://www.technoblogy.com/show?1GX1
And here's one using python:
https://www.modmypi.com/blog/gpio-and-python-39-blinking-led
If I were my 12 year old me, I would probably enjoy the second more than the first.
I agree with this, but I'm not sure how many of the students taking the MIT course in question are learning their very first programming language there.
Now if we were talking about a secondary school course...
Throwing objects and lambdas and type inference at kids without giving them any grounding in what a computer actually is and does is unfair, and leaves them building castles in the sky.
Assembly had a few weird architecturey things that you had to understand before things made any sense (e.g. registers, segment:offset addressing, stack pointers, calling conventions), but beyond that, all of the tasks were simple and self-contained.
C was a breath of fresh air after that. Things like pointers, which have a reputation for being confusing, make perfect sense coming from assembly.
Agreed with the caveat that C pointers aren't just memory addresses they just behave like that 99% of the time which makes it especially confusing for the 1% where the optimiser can "play tricks"..
In the end you're spending all day/week/month optimizing your CPU by stripping out gates, pipelining, all at a circuit/gate/HDL level, with your final project score computed numerically from how fast your optimized machine code program is running on your optimized home-grown CPU.
Probably one of the best classes I took when I was there. Doesn't really matter whether or not it was the first class or not I don't think.
I think the problem is that SICP's pedagogical approach (which people confuse with the language Scheme) is, in a way, pretty close to starting with assembler. You spend a lot of time exploring computation (with lambdas as your basis) at a very low level before you graduate to anything that feels "real" or practical.
(1) Learning Java before you learn a procedural language, to me, makes no sense, and turns a programmer’s formative foundation of programming into an object-only one.
(2) The difficulty in getting over the ‘hump’ (usually about 5-6 weeks in to learning one’s first language) is what turned me off programming when I was 13, but given a great intro course I was able to get over it and I’ve developed a deep passion for it and I couldn’t imagine life without it. So to put the bar at 3 languages, to me, is insane.
(3) Many (most?) people don’t start off saying ‘Programming is or will be my career’. Instead, you try it out and see if you can do it and if you enjoy it. To me, this is a fundamental misunderstanding in how people view programming when they are learning their first language.
A bit of extras: in today world we can't produce really anything new due to managerial-driven society and beside that it's better people do NOT really understand how things work to avoid not only embarrassments but also potential idea to radically wipe out certain kind of business models. So better saying: you can't understand the big picture! Keep play with thing Bigs&powerful give you, they came directly from the nature do not worry about it.
Sorry to have made few "potential-flamey comments" in a row but reasons written in the article have really no other meaning to my eyes. That's not intended to be political or flamebait, it's simply what I see. I do NOT start with scheme, I discovered it years after and I even do not love it too much due to it's n-th implementation incompatibilities, srfi and "sparse" documentation... But when I discover lisp-like languages in general I see a completely different world and really change my mind. Guile scheme, even with the lacks of libraries etc it's now one of my preferred way to express concepts.
Also as per explanation I can't accept as engineer and even as a citizen to make thing, under my responsibility, with my signature etc that I do not really understand. This kind of idea is simply the exact opposite of engineering.
uh, you know this is about MIT right? A school that has seen its acceptance rate dwindle to nearly 7%?
I'm European so I came from a really different (older/less reformed) school system and I'm old enough to see how it's change. I also casually interact with USA people and my conclusion is simple: having really poor schools "because there is college after" it can't really work. I see in EU, reform after reform, how unprepared become high-school students and how hard, if not impossible, universities try to "recover" them changing their programs. In the USA this phenomenon it's extreme so even with a super-low acceptance rate results have to be also extreme.
You simply can't get smart but ignorant people and in few years transform them in high-skilled and acculturated guys. Being smart help of course, but learn require time. The better you start, early, the better you'll end up after.
In this case, I think the areas in which programming and CS are applicable has increased so greatly it's now more feasible to have them start from a more general abstracted area and chose their focus as they grow - learning the tools and theory they need for their chosen focus.
If they start getting bogged down by more complex languages it prevents them from identifying after a year or two which areas they are interested in pursuing and focusing on.
This reminded me of a phrasing I once read, but never quite understood, in the "acknowledgement" section of the R4RS Macro appendix:
"Hal Abelson contributed by holding this report hostage to the appendix on macros".
Can anybody who was/is closer to the subject matters explain what this entails?
https://hn.algolia.com/?query=mit%20python%20scheme%20points...
so you only need to learn to be a plumber.
However, Python is a lousy choice for computer science, where clarity and correctness are much more important. It saddens me that an elite institution like MIT apparently can't see the difference.
FWIW, I have a CS degree, and my job is mostly engineering, but using a sound theoretical approach to problems has saved me many times. On the other hand, I've worked with several good programmers over the years who didn't have a college degree at all.
Edit: Never mind, its good now. ;)