JavaScript at Khan Academy
ejohn.org
ejohn.org
But does this result in a better outcome for the student?
How many other commonly used programming languages use prototypal inheritance?
Prototypes also have some niceties. They are very memory compact, unlike classes and instances. They are elegantly dynamic -- you can add and delete methods and variables, and even change who your prototype is at runtime. Methods in prototypes are very similar to functions, so you don't have to explain the distinctions there.
I think the main problem is that Javascript is such a screwed up language that it has soured people forever on prototype OO and no amount of semantic elegance will fix that.
In answer to your second question, here's the list of languages I know of. Only two are "mainstream", but in a field (CS) where quality is all too often inversely related to popularity, I'm not sure if that's a helpful metric.
1. Self
2. NewtonScript
3. Lua (via metamethods)
4. io
5. IIRC Python implements OO with something approximating prototypes internally but covers them with a class-based sheen when presented to the developer.
One notable difference is that `foo.method` is bound to `foo` in python, but unbound in JavaScript. This leads to lots of `foo.method.bind(foo)` because the former didn't DWIM.
The key similarities in my mind are:
1) In both python and javascript, the class and prototype are exposed and can be called explicitly if desired:
MyClass.method(my_instance, arg1, arg2)
MyClass.prototype.method.call(my_instance, arg1, arg2);
2) Python will automatically bind methods when you retrive them from an instance. Unless you explicitly bind a function in JS, the "this" parameter is specified at call time: whatever comes before the dot is used as "this". Ultimately they're both first class objects and the difference to the developer is notation: bound_method = my_instance.method
bound_method = my_instance.method.bind(my_instance);
3) Attribute lookups in Python behave very similarly to property lookups in Javascript. Python has a modified resolution order for searching for an attribute through its list of parent classes. Javascript will look for an attribute in a series of prototypes (since in JS, an instance's prototype is just an object, so it too can have a prototype). Python is superior here because it supports multiple inheritance, but overall the resolution behaviour is essentially the same.Can anyone think of any other common ground?
One case that comes to mind is how each language implements (what I call) the continuation pattern. Suppose you want to iterate over the vertices of a binary tree. In JavaScript, you would accept a callback parameter which you call with each vertex. In Python, you would yield each vertex to the caller. These are very different styles and lead you in different directions.
The usual counter example in this discussion goes like: "..but people are already familiar with the concept of categories of objects...".
I do argue with the following paragraph: I don't see why prototypes-based languages should be more memory compact than class-based, and class based languages can have dynamic addition of methods and variables (see ruby), and change of an instance' class (at least since Smalltalk 80 AFAICT).
In most class-based languages, when you create an instance, you allocate memory sufficient for all instance variables defined by its class and superclasses. But in a prototype language, when you create an object, you only allocate memory for the instance variables in which it is different from its parents. That often results in enormous savings, particularly in GUI widgets where you have zillions of instance variables, nearly all of which are left on default settings.
Most class-based languages do this because it allows O(1) lookup of instance variables. Whereas lookup in a prototype language may require wandering up the parent chain until you find the object which defined a given instance variable. That's the tradeoff: lookup speed for memory compactness.
There exist a few class-based languages which don't do this tradeoff. But I have yet to see one of this kind which _doesn't_ basically just implement prototypes underneath. Python is notable here: it doesn't have O(1) lookup to the best of my knowledge, yet doesn't allow the simplicity of prototypes either, so it's sort of the worst of both worlds IMHO.
> and class based languages can have dynamic addition of methods and variables (see ruby), and change of an instance' class (at least since Smalltalk 80 AFAICT).
And CLOS. Sure. But these are exceptions, and don't kid yourself, bolting them into class mechanisms comes at a cost of significant increases in complexity and speed (and loss of the O(1) advantage that classes provide). But in proto languages, you're just adding or changing a dictionary entry. It can't get simpler than that.
> For you first answer, I am not saying you are wrong, but I'd like to see some evidence (e.g. pointer to researches) that prototypes are "much _much_ simpler" than classes and instances.
I'm not sure if simplicity is of interest to academic research. But let me try with an example. In NewtonScript, to make a button which has a different x and y location, text, and override some function (say setText()), I'd say something like this:
myButton := {
_proto: Button,
x: 14,
y: 15,
text: "Hello, World",
setText() begin here's the code blah blah end
}
Done and done. In Java, I'd do: public class MyButton extends JButton
{
public void setText() { here's the code blah blah }
}
MyButton foo = new MyButton();
foo.setText("Hello, World");
foo.setLocation(x,y);
If Java had done anonymous classes right I could have used that to just set the x and y and get a little closer to the NewtonScript example. But the point is: in the proto language I didn't need to declare a class just to override a method. You have to admit there's some elegance and simplicity there. Indeed, my Newtonscript code tended to be very short and simple, whereas my Lisp/CLOS, Python, and Java OO code tends not to be.But this looks like an implementation detail that does not seem related to prototypes vs classes, but more to dynamic vs static ones (e.g. Cecil does prototypes without storing a dictionary in the object, while ruby does classes with dictionaries)
So we may be in agreement, but referring to different things.
To be fair, Javascript is the easiest language to teach through a website, but that's it. The goal shouldn't be to make the teacher's life easy rather then providing the right tools for the student.
Javascript is not ideal, but it's quite good, and it's there, already running in a sandbox on the student's machine.
CS requires a deeper understanding that JS gloses over (obviously) and programming in general can be more easily learned in either a cleaner (python) or more rigorous (java) language. I'm only a few years into my programming career and vividly remember trying dozens of tutorials in half a dozen languages before deciding on really learning through Python. If I were to rank languages to start with they would look like this:
Goal: Learn to Program
Python, Ruby, Java, PHP - yes, really, JS
Goal: Learn CS
Java, C, Assembly, C++
It's refreshing to see such passion, but I feel compelled to offer some advice: languages are just "tools." No one tool is better than another for all situations. JS seems like a reasonable place to start new programmers. Like anything in software, it has its tradeoffs. Some thoughts:
* While the new programmer won't learn about call stacks or different parts of memory (considered essential when I learned to code), the programmer will learn to solve problems using control structures, method calls, recursion, and iteration. These are fundamental skills I see re-used in almost every language. Are there other awesome skills like functional programming I wish they would learn? Sure, but you have to start somewhere, and I support starting at if-else-then logic.
* Writing JavaScript is easy. No command line. No installing software. No compiling. No IDE. Just open your Web Console in Firefox or JavaScript Console in Chrome. Seriously, if you are teaching the masses on the internet, what better way than use the very tool they used to view your website?
* Writing JavaScript is in fashion. From Node.JS to last week's Tower.JS, JQuery, JSON, or the "new" HTML5 rage: JavaScript is popular. What better way to be relevant than teach what the industry is using? I support teaching popular things to introduce people to our industry.
[edited: /. not ./ derp!]
However, CS is not all low level--there is much to do at higher levels of abstraction. In fact, I think starting out at a high level of abstraction (e.g. Scheme) and moving down is the best option. (Coincidentally, Scheme with SICP is a great here.)
For the basics, I think Scheme -> C -> MIPS -> Simple MIPS CPU is a nice progression. After that, the languages you use would depend on the domain you're studying. (E.g. if you're studying programming languages, I'd go with Haskell.)
As for learning to program, I think Python is woefully overrated. JavaScript is a nice (I think nicer) language and , moreover, is easier to bootstrap--you start out in a familiar environment (the browser) immediately.
[1]: http://mitpress.mit.edu/sicp/
I learned Scheme (and a bunch of other stuff) with such a course and it was awesome. Most of my friends and I thought the course was easy but apparently others didn't, and I gather it actually has a reputation of being relatively difficult around here.
If you're less motivated or have less time, I've heard really good things about The Little Schemer[2]. Our course also suggested Simply Scheme as an introduction to it. This book was written by our professor, who is the best teacher I've ever had for anything, and it's available for free online[3], but I've never read it.
[2]: http://www.ccs.neu.edu/home/matthias/BTLS/
[3]: http://www.cs.berkeley.edu/~bh/ss-toc2.html
I don't know of any really good shorter tutorials, but I'm sure they exist. That said, if you have a little bit of time, you really should read SICP--you'll learn a ton about CS as well as learning Scheme.
The language you learn doesn't have to be the language you end up using, or using to learn CS. It just has to get you off the ground.
So many people get turned off from a subject when they "don't get it" at first, so really, the challenge is providing the least painful intro to programming. Personally, my first languages were Logo and Pascal, and since I almost wrote off programming before Pascal as being too hard, I'm glad I saw C++/Java only afterwards.
One thing that enamors me about the JS approach is that it reminds me a little of Logo -- not only are the results are very immediate, but the visual output gives us a constant second avenue of insight into what we're doing. I'm sure many have seen Bret Victor's talk "Inventing on Principle" (http://vimeo.com/36579366), and he underscores the benefits of direct feedback to what we're doing. I have a friend taking CS10 at Berkeley this semester, and the Scratch-based environment also seems equally cool.
That being said, I don't use JS much (haven't really touched in it 10 years), but I believe it when people say it's (still) horribly irregular. In that regard, it might be on par with some other scripting languages (e.g., Ruby). So the distinction to be made here is that JS might be easy, but (as we can see) not simple.
As people who program seriously, we need simplicity in a language in order to build up large apps that we can easily reason about and don't bite us in every corner. (Note: simplicity in a language doesn't necessarily mean it's going to be easy at first.) But I wonder if we've been so used to programming that we forget how it can be hard to learn at first, and we're just ruling out the easy approach, which would exclude just what some newbies need.
JavaScript is actually a very simple language modulo a small set of irregularities. Most of these irregularities go away with "use strict", which is basically the modern version of JavaScript anyhow. (And even more improvements are in the pipeline with future versions, which you are free to use for projects outside the browser!)
While there are several reasons why I would not choose JavaScript first for "serious" programming (although it's pretty high on the list), these reasons are shared by most of the other popular languages like Python, Java and C++. (I also think all three of these languages are more complex than JavaScript.)
If people who programmed "seriously" actually cared about simplicity and reasoning about code, we'd see much more Haskell in the wild. But instead we see the three unfortunate languages I listed above: Python, Java and C++. (Rounded out with mostly similar languages.)
What are the current trends in language use? Are people moving away from Python, Java, and C++? and if so, to what?
What is their goal. It seems that John Resig only wants to teach his favorite language/tool JS.
Main goal must be to teach fundamental CS concepts, programming basics, algorithms and data structures. Language choice is must to be appropriate to that goals.
He talks about teaching prototypal inheritance, is he serious? For those how have not any prior programming experience.
It seems, that he has no any prior pedagogical experience. Why that guy make such decisions and why Khan academy can't hire more experienced CS teacher.
Yes, I know, he is great guy who wrotes jQuery, but pedagogy and JS programming is two very different areas.
Oh, wait, you wanted to inherit from multiple places? That's a little harder; we'll need a for-in loop, but it's not too much code and it alerts you that you're probably Doing It Wrong. But wait, what will you do with the constructors? You don't have two `super()` functions or for that matter even one `super()` function. How do you call the last constructor? Oh yeah, that's right:
function Mammal(s, n) {
this.species = s;
this.noise = n;
}
function Pet(n) {
this.name = n;
}
function PetDog(name) {
Mammal.call(this, "Canis lupus familiaris", "Woof.");
Pet.call(this, name);
}
... you `.call(this)` it to call it on this. And now both constructors are called where and how you need them, with no confusing "super()" function that you need to teach three times to people before they get it.Compare this to Java where the moment that you want to merge two interface declarations you find yourself opening up a new file to do it.
I mean, Java has some nice points, but its idiosyncrasies make it pure pain when you're teaching CS 101. Here I was wanting to teach kids on day one about sorting strategies with a deck of cards, culminating in quicksort: "why don't we sort black from red first, then within black sort spaces from clubs first, then within spades sort high from low first...". That works and then I want to show them what it looks like in Code and I'm suddenly all like:
"Okay, this file is named Test.java and then there is a magic line `public class Test { public static void main(String[] args) {` which is a magic incantation to appease the Java demons living inside the `javac` program, and then we have to have a Card[] and that requires another file... oh f!ck it I'll just use integers, an int[]."
All of that stuff is idiosyncrasy which stops you from Getting Work Taught. It might help with Getting Work Done in large corporate dev teams, but it does not help with Getting Work Taught to small classes of confused individuals.
I think Python is a worse choice because it's also more complicated and less elegant than JavaScript (and it has its own share of pitfalls), but that seems to be a minority opinion around here.
Prototypal inheritance is much simpler than classical inheritance--you don't even have to introduce the idea of a class. I think it would be easier to teach prototypal inheritance rather than classical inheritance to people with no programming experience.
The last two paragraphs of your post seem to mostly be an ad hominem.
JS was built for small scripts on web pages.
I think Python is a worse choice because it's also more complicated and less elegant than JavaScript (and it has its own share of pitfalls), but that seems to be a minority opinion around here.
You wrong, Python is much elegant than JS. Starting from syntax which was derived from C/C++ like languages. With a lot of bugs and confusing behaviors (some of was mentioned by Resig itself).
Code in Python is very clear and looks like pseudo-code. It's very easy to read and very easy to start writing in it.
JS - specialized language for Web. Python - general purpose language.
Prototypal inheritance is much simpler than classical inheritance--you don't even have to introduce the idea of a class. I think it would be easier to teach prototypal inheritance rather than classical inheritance to people with no programming experience.
There should be no inheritance for beginners. It's not even core CS concept. No classes, no OOP in any kind of it (prototypal, classical).
I think with this approach we will get not CS professionals. We will get JS script kiddies.
Python may look more elegant, but there are some hidden issues--weird variable scoping, dubious desugaring and crippled lambdas. (Also, the idea of a function as value is easier to understand with the word "function" rather than "lambda", something I would probably have changed in Scheme if using it to teach beginners.)
Moreover, Python actually shares several of JavaScript's misfeatures like weird loop scoping and the arbitrary statement/expression distinction. On top of this, Python is far more hostile to functional programming than JavaScript. (And this is by design!)
JavaScript is a much smaller language--Python has far more baked into the language itself. This is why I find Python less elegant--thing like "in" have no place in the language; they should be expressible as libraries. An elegant language is small but can be extended by its users; Python's philosophy seems to be the opposite. This is, again, where Scheme really shines.
I do not see why Java is a prerequisite to teaching "programming in big"--nothing stops you from teaching modularity and loose coupling in JavaScript. If anything it's easier because of anonymous functions and libraries built around passing functions around. (Java does have a static type system, which is an advantage, but it's a pretty bad type system.)
Also, you seem to be perpetuating the same common myths about JavaScript--it is as much a general purpose language as any and not particularly specialized for small programs or the web. It's certainly as general purpose as Python except perhaps a little lacking in some libraries. And with the advent of Node, it's quickly getting all the libraries it needs.
About inheritances... O no another craizy concept I have to learn...
I learned Pascal in the late 80's and I would never teach my children it, or send them to a school that used it.
It was dumb then, we should have used something like Smalltalk, and it is simple weird to mention it now.
A lot of youth in the United States today aren't flocking to programming. We need more. And yet it's strange because programming as an industry is what afford young people the most opportunities. When was the last time you saw a major non programming company have core contributors < 30 years old? < 25 years old?
JS as a language, TextPad as an editor, and a Browser as a runtime environment is a far less intimidating barrier for students. People can see the results in a medium that's familiar to them (a browser). It's also free and readily available. No installs, no environment paths. nothing to discourage them. In conjuction with HTML, they can see how JS/programming changes what they're viewing. It will help bridge a lot of people's thoughts into "oh, wow, I can actually do this and it has a tangible effect". When growing up I was wondering how the hell a printout to a console would have any benefit to me. Yet, that's how I was taught (in C, C++)
It's also been difficult recently to find frontend engineers. Colleges don't train for this - it's all algorithms and abstract concepts that are great for backend developers. That's why there are so many more backend engineers out there than front end engineers. The FE side is under represented.
There are some arguments that this is a terrible first language because it's not as rigid as the others. But honestly if you can't learn a language and then apply the concepts and learn new ones to pick up new languages, you probably shouldn't be tackling those tougher languages in the first place.
With HTML5 apps coming down the pipeline, people WILL need to know JS and we as a technical industry will need to accept that they too are part of the product/output of science/tech/web/mobile. Some people won't be diving in more beyond that, but if they do, they at least have a foundation to build off of as they get into more robust languages.
JS gets people in the door, and it's not going to preclude others from picking up other first languages. It's a solid step for bringing more people into the fold. It's not going to be the best for theory, but there are places and time for that.
JavaScript is a language that misses a lot of important CS and the most important of all is language build in modules.
Apart from that you should start with either a fully functional language or a fully imperative OO language. These are theoratical distinct language classes. And JavaScript is in the middle, you will confuse people.
At my university they started with Java.. also not the best choice. However OOP is very important and just neglecting that initially is not a good idea.
From a theoretical point of view, javascript is not the best language to start with. In fact as a language, its quite inferior to other function-imperative language such as Python.
If your argument is that a choice should be made between teaching objects and teaching functional programming, I disagree completely. They are complimentary models of programming that are not in conflict. See the paper "Open, extensible object models" [1] for an example of how the object/lambda combination can be extremely powerful. Considering that, JS lambdas are far more powerful than those in Python (they can have multiple lines, for one).
Javascript certainly has design flaws, but it seems like a great fit for teaching programming, in that it is a small language that covers a large number of important programming language concepts.
I was talking about functional vs imperative programming. They are not in conflict. But there is a theoretical difference between both of them. And CS is initially about theory in my opinion. Learning turing-completeness, lambada-calculus and logic is more important. Thats why pure language are better at university.
About JS lambdas and python... thats just plainly not true. and btw: JS doesnt even have list comprehension!
Your last point: JS has a lot of concepts. And that is the main reason NOT to use it, as it will confuse students. But i agree, this point is debatable. It just doesnt feel right.
Except for creating an HTML-file and understanding how all that works.
> and the OS becomes (to a degree) irrelevant.
This is pretty much true for any language as long as you don't use platform-specific features (fork).
> Further, javascript is an easy language to prototype in, and, at the basic level, easy enough to teach and write.
"Easy language to prototype in"? Both Python and Ruby are equally "easy", but comes with even more batteries included. They also have a consistent object model, as opposed to JavaScript's prototype-inheritance-is-cool-but-let's-mix-in-constructors-from-classical-OOP. There's pretty much nothing like JavaScript's prototypes in any other languages (Self/Io works quite differently), and I don't really see any gain in teaching that to students early on.
I do have to agree with you about the ugly mix of inheritance models, but for the initial teaching phase, you could largely ignore that before moving on to a different language to teach either true OOP or functional programming.
Using chrome? Hit [ctrl+shift+j|cmd+option+j] and you can write JavaScript without any HTML necessary. Other browsers have similar consoles that need no HTML to write JavaScript.
REPLs are fine to experiment with, but it's important to learn how you would write "real" code. Dumbing down this essential concept is just silly.
All modern browsers has JS console. That's dev environment setup freely for you. And if you use FF, enhancing that env with Firebug is just a few clicks away. WIth the rise of web apps nowadays, this is actually a very good move.
Not passing judgement either way, but I doubt you're ever going to agree with each other on this basis...
Remember, the introductory programming class is all about teaching students to talk to their computers in a methoidcal, step-by-step fashion. It's not about the finer points of language design.
Pretty much any open-source language is available on all platforms. Besides, you still need to setup an editor, so it's not like you can skip the whole "install software"-step.
> can be deployed to others easily
In the beginning this doesn't actually matter too much. Beginners are usually aware that they're not creating something that all their friends are going to use, and it's often better to show it to them face-to-face so you can explain things. Sharing code with other students on the other hand is very useful, but JavaScript isn't any different here ("look at my .html" vs "look at my .py").
> a reasonably powerful API (but not powerful enough to shoot your foot)
JavaScript has few built-in libraries, and the DOM API is very HTML-specific and a horrible mess. I don't quite see how these APIs make the students become better programmers; just understand the quirks of HTML more detailed.
2. Creating a Web App to follow programming concepts is something John Resig knows how to do. Check out his Advanced JavaScript page for examples:
3. No installation needed. No one has to have permissions to install or modify software or the OS. That's a huge hurdle. If you're at a public library or borrowing your brother's computer, you don't have to worry about permissions, settings, downloads, etc. You're already setup to start with just learning.
Obviously, to become a better programmer you have to learn some more languages, but JavaScript is not going anywhere anytime soon. In fact, there is a higher demand for JavaScript programmers than ever. Why not learn it?
Another thing that is important is that it is simple to get quick feedback without time wasting compilation and re-running.
You can do amazing things with JavaScript, and some of them you won't do in Python.
I agree that modules are important.
They are so important I don't think that entirely built in module systems are good enough.
You need to be able to bind to private modules, and load and unload modules like OSGI. You need to be able to configure and have multiple instances of modules, like with Spring.
It is remarkably natural and simple to create really powerful module constructs in JavaScript.
It is really easy to implement a good OO design in JavaScript.
I find Python really nice too. Haskell is interesting.
I am sure Java is worse than C# in many ways, and better in very few, but even Java has some things I miss.
This is why I think Scheme is a great language to start with: it is both a good imperative and a good functional programming language (and it's easy to reuse the syntax for a logical programming language too!). On top of this, it is much simpler than JavaScript or Python--you can learn the syntax in one or two sessions.
Coincidentally, Python may be a fine imperative language, but its support for functional programming is pretty pathetic.
That said, I think if you teach JS in the context of Node.js with liberal use of quality npm packages like mocha for unit testing, etc. it could be a fantastic environment for beginners and ease a lot of frustration. Just having a REPL is reason enough to use Node for beginners.
http://fleetinbeing.net/beans/
Still needs a decent JSON viewer before I start on the tutorials. It's a problem that once code is evaluated, it turns into Javascript. JS2Coffee isn't a satisfactory solution. I suspect teaching some Javascript, especially stuff from Crockford's The Good Parts, will be necessary.
The advantage of course is it can be compiled and run natively in a browser. The syntax is simpler, but there are corner cases. Though plain javascript also has corner cases CoffeeScript doesn't have, and js syntax is more intimidating.