I have to say that Java is the absolute worst language for pedagogy. Before people can write "Hello world", they're told they have to write "public static void main(String[] args)", which are presented as magic incantations, "don't worry about those yet". Thus begins the corporate-style coding culture of bashing stuff without understanding it.
The stated reason for starting in Java is so that students can get coding jobs based on one or two CS classes, but two issues come to mind there. First, I generally wouldn't hire someone (in a technology company) who took one CS class and didn't continue-- but at least if she passed an SICP-style course, I'd know that she learned how to think about computational problems. Second, you don't "know Java" when you come out of school. Java is actually highly complicated (in good ways and bad) and the average college student hasn't been exposed to all the mess of it (and that's probably good, because, while OOP means about 20 different things to different people, business-style OOP is cataclysmic).
While I personally agree with teaching something other than Java, there is one big advantage of Java you have overlooked-- as the core language is so simple, bugs caused by incorrect use of the language tend to be "shallow" (bugs caused by algorithmic mistakes can still be very complex of course).
An easy example of this is compile-time errors -- the most complex compile time error you can get of Java tends to be nothing more than "mismatched bracket" or "incorrect function call", whereas even fairly simple Haskell code can produce very complex error messages, and ghci (for example) tends to make things worse rather than better.
Java isn't perfect and has been getting more complicated, boxing & generics for example, but still is not close to the pain one can create in a handfu of characters in Haskell (of course, C++ has the same problem, for different reasons).
Personally, I see Haskell as the C++ of functional language, and therefore would prefer not to teach either Haskell or C++ as a first language.
That requires support external to the language, right? I haven't seen it widely used in the codebases I've worked on, and it adds additional verbosity to an already verbose language. It's yet another argument against Java as a first language.
I've seen plenty of NullPointerExceptions in enterprisey Java to know you generally do get them.
> An easy example of this is compile-time errors -- the most complex compile time error you can get of Java tends to be nothing more than "mismatched bracket" or "incorrect function call"
So, you're saying it's a benefit that the Java compiler doesn't help you out with anything very meaningful? The "complex error messages" are one of the most significant benefits of using Haskell, for me, because it means that the compiler it helping me out with more than just trivial syntax matters.
Except that Scala already is ;). Haskell pretty much sticks to functional programming and resisted adopting other paradigms (e.g. OO via O'Haskell). Scala, on the other hand seems to adopt as many paradigms as C++.
When I used OCaml, I almost never used the object system. I didn't need it.
The "full" OCaml is pretty complicated, but most of the libraries don't force the "O" on you. (That said, if you're going to use OCaml, you should use the Jane Street libraries, which are far better than the standard library.)
I agree with the point, but the argument -- that by arbitrarily ignoring features you come up with a simple core language -- can be applied to Haskell (and pretty much any other language) as well.
If you exclude typeclasses, extensions, and IO from Haskell, you get a very simple language. (I personally find the error messages easy to understand when avoiding those)
Related: how GHC compiles Haskell code, including the "Core" language and lots of desugaring.
I have written quite a bit of Haskell, I'm not sure what you think is wrong with my belief. Also, I like C++ :)
Both are fairly big complex languages with horrible error messages, horrible compile times (if you use template haskell in particular), with a whole bunch of gotchas you have to learn to get good performance (the haskell gotchas are very different, and often based around lazy evaluation / memory bloat). Both have sharp edges that come from being old languages which have evolved over time.
However, both languages are good in practice for actually getting things done.
That is a very common claim from people posting misconceptions that could only arise from second-hand info and a lack of direct experience. I have a very hard time believing it given that you claim haskell is large and complex.
>Also, I like C++ :)
I won't hold that against you.
>what you think is wrong with my belief
Well, everything you just mentioned except the horrible compile times. Haskell is a relatively small language, and is not complex at all. In fact it is quite simple, and very consistent. I don't know what you mean about horrible error messages, and you do not need to learn any gotchas to get good performance. What you need to learn is very simple, very clearly spelled out in the docs, and is no more than you need to learn in any other language. Avoiding unnecessary laziness is no more difficult than avoiding unnecessary strictness. I can't think of a single "sharp edge" haskell has, I suspect we must have different ideas of what a sharp edge is.
> That is a very common claim from people posting misconceptions that could only arise from second-hand info and a lack of direct experience.
Do you think that I, and an apparently large number of other people on the internet, spend our time insulting Haskell without having used it? That some great anti-Haskell conspiracy is being waged by evil groups unknown?
I haven't written large enough Haskell programs to have performance problems myself, but I work with people who have. People who have to keep an empty monad around because removing it doubles the run-time of the program, and make substansal changes to get programs into an acceptable (<16GB) amount of memory. Also, there are plenty of horrible error messages. Having a random google, here's the first one that comes up. While I can just about figure out what it means, it is several levels more complex than anything that would ever come out of Java. Stackoverflow is full of Haskell questions which are "I don't understand this compile-time error I am getting".
It was a PhD student's program, but the problem was verified by more than one knowledgable Haskell programmer. I'll see if I can get them to write it up somewhere!
>Do you think that I, and an apparently large number of other people on the internet, spend our time insulting Haskell without having used it? That some great anti-Haskell conspiracy is being waged by evil groups unknown?
No, it seems like a relatively small group. And I did not suggest ill intentions, merely ignorance. Do you seriously think "some people repeat second hand info about topics they lack experience with" requires a "great conspiracy waged by evil groups unknown"?
>I haven't written large enough Haskell programs to have performance problems myself
So, you are confirming exactly what I said, that you don't have experience and are repeating second hand info. Why then did you feel the need to invent some sort of conspiracy theory nonsense as a rationale for your behavior?
>People who have to keep an empty monad around because removing it doubles the run-time of the program
That statement demonstrates such an obvious lack of understanding that I am almost able to believe you are ill intentioned. That makes absolutely no sense, it is like me saying "C is bad because I have to keep an empty function around or it doubles run time".
>make substansal changes to get programs into an acceptable (<16GB) amount of memory
That is too vague to be meaningful. Were they working with >16GB of data? Did they just have a memory leak? Do you understand that memory leaks can be created in every language?
>Also, there are plenty of horrible error messages. Having a random google, here's the first one that comes up
Are you trolling? That is a trivially simple error message. It is a simple type mismatch, the compiler expected X, it got Y. Which is precisely what it says.
>Stackoverflow is full of Haskell questions which are "I don't understand this compile-time error I am getting".
Stackoverflow is full of everylanguage questions of "I don't understand this error I am getting". That is completely meaningless.
Haskell is a relatively difficult language to try. Introductions and books almost seem to expect you to understand the syntax when you begin. And I/O is introduced late, which makes it hard to play around with.
Learn You a Haskell is an excellent introductory text and I see no way in which it "expect[s] you to understand the syntax when you begin." It walks you through things very explicitly. Yes, IO is introduced late, but it is not necessary for playing around with the language. IO is only necessary for play in languages that don't have a REPL.
I think you are forgetting that everyone who uses haskell has obviously gone through the trying it stage. It is not that hard, I did it. I just had a couple of PHP programmers do it without any problems. LYAH assumes you know very little, and explains things very simply. It gets to IO plenty quick enough, and before that it is showing you how to play around in ghci where you don't need to care about IO.
Just because you should not explain to students what "public static void main(String[] args)" is the first day does not mean that you can never teach them. Actually, if your students cannot understand what this line is after one full class of Java, then the problem is with the teacher, not the students.
> Actually, if your students cannot understand what this line is after one full class of Java, then the problem is with the teacher, not the students.
I think you're dead wrong about that. Assuming somebody with no programming background at all, here is a (definitely not exhaustive!) list of things that must be learned in order to understand that line:
Method visibility, what is a "method", what is a "function", what is a "class", probably what is an "object" (because it is otherwise difficult to understand why a "class" is a useful construct), "static" methods, either need to hand-wave the use of the term "static" for methods associated with a class or know a reasonable amount of history and/or computer architecture, the idea of a "return type", oh, the idea of a "type" come to that, "void" itself, "main" and generally the idea of a program entry point, function arguments, the "String" type, what is a "character", how are characters made into a "String" (arrays and encodings with various amounts of hand-waving), the "[]" syntax, and arrays of arbitrary length.
A class period is, what, 2 hours? No, it doesn't matter how good you are as a teacher, you can barely cover all that material in a single period, let alone do so in such a way that the students have any idea what you're talking about. Teachers finding themselves a month (or three!) down the road telling their students "now you have enough background to go back and understand the very first line of code you wrote!" is absolutely an anti-pattern.
Having learned C and C++ before even touching Java, "public static void main(String [] args)" arbitrarily shoved inside a class is still an aspect of the Java that absolutely annoys the crap out of me. Before you even print "Hello world" to the screen, you're exposed to an obscene amount of opinionated design (classes! classes everywhere!). Given a competent instructor, students should learn to "break out of main()" as quickly as possible. However, the class where I actually learned Java formally had an adjunct professor who would put EVERYTHING into one class so that students wouldn't have to learn about code organization so early (IMO a huge mistake).
All of that aside, I find it amazingly stupid that a best practice for Java has you creating a specific class like MyCoolAppRunner with only one MAGIC function whose only job is to load ANOTHER class to handle the actual app. IMO C and C++ get it right by having main() exist in the ether by itself -- it indirectly abstracts the stack and heap in a way that makes MUCH more sense than the way Java handles things.
The important part is not the 'never.' The important part is that the _very first thing_ you tell new programmers is "Don't worry about this, it's magic, just ignore it."
This sets a certain kind of tone and expectation about programming that's quite poor.
#include <stdio.h>
int main() {
printf("Hello world!\n");
return 0;
}
Woo! Your first program and I count, at most, 2 things that could be described as "magic" for someone who's never seen C before (the stdio library and double quotes being syntactic sugar for an array of chars). Even then, those two things are deterministic, so they won't remain magical for long.
"But what does 'return 0' do?"
"It returns the value zero to the calling process."
"Calling what?"
"The process. Usually it will be the shell."
"Wait, you just said process, what is this 'shell'?"
I strongly disagree with you. Public, static and void refers to three concepts that are not easy to grasp for starters. After a course they might more or less know what is the magic doing but in most cases they don't understand the underlying mechanism.
On the other hand, you will get students distracted by all those concepts and they don't spend time in what it matters on that level (learn how to make the machine to compute)
This doesn't happen in Scheme (for instance) where everything is clear and simple, two qualities that are great for starters and let them to focus in the algorithm part rather on the language shenanigans.
> Before people can write "Hello world", they're told they have to write "public static void main(String[] args)"
Bootstrapping is hard. My introduction was in Fortran, and I had written a couple of sort implementations before I ever learned to enter an array by any means other than hard-coding it into the program. Kernighan and Ritchie did an excellent job with bootstrapping programming concepts in their book on C.
And, somewhat off-topic, but since you mentioned Hello World and I mentioned K&R, it's worth noting that K&R's meaning when they said that Hello World was the first program you should write in any language was that you need to be able to run something. You have to be able to enter the program, compile it, link it, run it. Today a book can offer an example for Linux, one for Windows, and one for Mac and cover nearly everyone. Not so simple in 1978, when K&R first came out, so they basically tell you to get Hello World running with the help of a local expert (perhaps a teacher), and then come back to the book and start learning.
A lot of the arguments against Java seem to focus on "Time-to-Hello-World". While I agree that the first time you execute a program and see those magic words appear on your terminal, I don't think we should judge a language on that. Visual basic has a very short TTHW (esp. if you take into account the time spent on learning about terminal emulators for most languages), that doesn't make it a good language.
If you take an OO programming language as your teaching language, you need to introduce a number of concepts first.
Hr 1: Talk about classes and objects. Introduce the Car and Bike object, that both have the method 'steer()', the attribute 'wheels' and only the car has the property 'hood'. Introduce return types here, as well as arrays.
Hr 2: Then explain how the 'color' on Car is public, while you'd like the accelerate() method to be private.
Hr 3: Explain how some methods and attributes are static. what is a property of the concept 'Car' and what is an attribute of an instance?
In Hr 4 you introduce them to the classes String and System.
Your students will now know:
-class
-public
-static
-void
-String[]
You can now tell them about the 'magic' that makes things start, the 'main' method.
Class MyFirstProgram {
public static void main(String[] args) {
System.out.println("Hello World");
}
}
No magic, and a nice start to becoming a proper OO-programmer.
If you want too teach them FP, Haskell is not a bad way to go. If you want to teach them OO, Java isn't as crappy as people say it is.
There is always a level of hand waving that will go on in any introductory course, for a lot of reasons. You have to keep in mind that the majority of students come from highly different backgrounds.
The stated reason for starting in Java is so that students can get coding jobs based on one or two CS classes, but two issues come to mind there. First, I generally wouldn't hire someone (in a technology company) who took one CS class and didn't continue-- but at least if she passed an SICP-style course, I'd know that she learned how to think about computational problems. Second, you don't "know Java" when you come out of school. Java is actually highly complicated (in good ways and bad) and the average college student hasn't been exposed to all the mess of it (and that's probably good, because, while OOP means about 20 different things to different people, business-style OOP is cataclysmic).