I have been teaching myself how to hack. I see that the first real software engineering classes in most schools is taught in JAVA, usually a data structures class. Should I even bother.... I see the merit of learning ground level stuff , like memory management seen in C/C++ but with JAVA is it useful to learn even if majority of web development is done in LAMP ( I should say majority of web development interesting to me, I know there is alot of JAVA out there) Does anyone know of a good book/tutorial to learn data structures with languages such php/ruby/python.
I only know Lisp and absolutely love working with it and the results we're getting with our web application (I was not a CS major), but my partner who is a Software Architect by profession tells me that programming in Lisp takes about half the code and effort of Java with more impressive results. (See Paul Graham's essays on Lisp: http://www.paulgraham.com/lisp.html)
Lisp is great but Python/Ruby are a great halfway point between C and Java and the purely functional Lisp type languages. It's tough to say whether you're better off learning Ruby or Lisp first. It would probably make a good PhD project for someone to compare the teaching of programming to first-time students with Pascal, Java, Ruby, and Lisp.
Anyways, www.hacketyhack.com is a great integrated IDE for learning the syntax of ruby.
Lisp is not at all exclusively functional. The best Lisp is, but you can easily write iterative code in Lisp as well. It's just that most Lisp programmers don't because they realize that the functional paradigm is usually superior in terms of creating clean, simple code that is easy to understand later.
Just to nitpick, any language that allows functions 'allows' functional programming to some extent. More seriously, any language with higher order functions, lexical scoping, and closures can be considered appropriate for functional programming.
You probably meant languages that are biased primarily towards functional programming, as opposed to others where FP is not the dominant paradigm. You have to specify that much if you are going to include the Lisps but leave Python out.
Your title is broad but here you say you want to do web development. Many of the people here are interested in programming for programming's sake, so a lot of the advice will be computer sciency. That's great, but if you just want to make stuff you can safely skip theory for now and get your hands dirty producing real stuff and fill in the gaps over time.
The key is to learn best practices of whatever language you choose. Don't learn bad habits. Read the authoritative books and don't take short-cuts. Don't be the guy writing code people cry at having to maintain. Avoid "cargo cult" programming, where you just paste code you find into your programs without fully understanding it. I recommend never pasting at all in fact. At the very least re-type everything as you're learning and try to understand it as best you can.
You can safely skip haskell, lisp, prolog, and all those languages you will never get friends to help you with, many books to read, or libraries to leverage. At least until you've got enough experience to be mostly independent of assistance.
With the use of best practices it doesn't really matter if you choose: Ruby, Perl, Python, or PHP. I'd ignore Java because it has so many training wheels, and the others don't. These can all work extremely well for web development and anyone who says different is selling something. The Truth™ is that Perl5 is the best and Perl6 will make them all obsolete :-)
Great to see Perl is coming back into vogue in these kinds of conversations. It's gotten a bad rap for a while, because it's so easy to write really messy and ugly code...but it's also extremely expressive, and contains more functional constructs than even Ruby or Python. Perl 5 didn't get objects right, but they aren't awful (not nearly as big and clunky as Java/PHP). Perl 6 really will be a killer. I watched Audrey Tang's recent video about it, and it was just astounding how far they plan to leap with Perl 6...I must have known it was coming, since I read the apocalypses years ago, but seeing the example code blew me away. It's still a pretty good learning language, and an unbeatable "get things done" language because of CPAN, but if pressed I would have to recommend Ruby or Python for first time programmers.
I was about to chime in Perl but I read down to this. I'm currently using Ruby now but my first step into hacking was Perl. So I have a soft spot for it. If Perl 6 can live up to it I will not have any qualms hacking in Perl again.
True on the surface. But Ruby's everything-is-an-object is a big difference in the way you think when working in each of the languages. Ruby definitely guides you into an OOP mindset, while Perl leaves all paths open...I don't necessarily consider this a win, but it is a pretty big difference in the way one thinks, even if the syntax of Ruby is immediately comfortable to a Perl programmer.
We almost never use OO in our Perl codebase, except where bolting on OO makes a lot of sense (specifically, the UI functions, some CPAN modules that have a more natural OO interface), but in the Ruby code I've written it's all objects and it never feels forced or bolted on. Partly, it's the tasks we're doing where functional programming makes more sense, and partly it's due to having a large codebase that pre-dates Perl 5. Oh, yeah, we also have a huge swath of disparate data being passed around amongst different systems and services, and it's very natural to pass them around as arrays and treat them similarly to lists in lisp. map, grep, shift/unshift, and pop/push get a lot of use in our code. I'm pretty certain we'd do it differently in Python and we'd probably do it differently in Ruby. It'd probably take quite a bit more code in either of those languages, but it might be more readable on first (and second) glance.
Perl 6 will change some of our practices (in three or four years when Perl 6 is wide-spread, anyway), but not all of them. Objects will be beautiful in Perl 6, so we won't avoid them, and argument passing will be much cleaner (right now we pass around refs to arrays a lot, which is somewhat fragile when API changes happen), so those things will change, but our treatment of data will probably remain similar.
So, I agree with you about Ruby syntax. It looks very similar, and is very comfortable to me, as a long time perl coder. But when you actually start building things, the comfortable paths diverge quite a bit.
I think lisp will be adequately enunciated, so I'll move on to the others
Haskell is a lazy, strongly-typed functional language. It's syntax is very close to mathematical notation, and it enables code reuse by not allowing side effects. It'll teach you to think in actual algorithms, where most languages teach you to think about how to implement those algorithms.
Prolog is a logic language. It'll teach you logic, and some of the fundamental ideas from that field. Backtracking search, unification, and other interesting ideas.
Forth is a reverse-polish-notation stack language that is very 'close to the metal' and yet a higher order language than C. Forth will teach you more about the workings of a computer than anything but assembler, and it won't break your soul like assembler might.
Erlang is strict strongly-typed functional language that is all about concurrency. Right now it's probably the best language to write highly concurrent applications in, and, as it turns out, most of the internet can be made highly concurrent.
Smalltalk is the mother of all object oriented languages, and shares with lisp the interesting concept of a running image. In smalltalk, everything you do is in a live instance of an image, and to deploy, you simply move the instance over and run it on the server. This also one of the first languages to have an effective refactoring browser.
Python is a dynamic object-oriented language that incorporates features from a lot of previous languages. It's got some interesting things and a fairly nice syntax. Take a look at TurboGears, Pylon, and Django
Ruby is a dynamic object-oriented language (lisp + perl) that is (like lisp) all about metaprogramming. Ruby has also got an interesting framework that is becoming notorious, Rails, which makes OR mapping and quite a few other things brain-dead easy. If you get into the internals of rails, you'll learn a lot about metaprogramming.
C is The Language. If it has to be fast, small, and close to the metal, C is the go to language (no pun intended) There are a lot of situations where you'll end up needing to rewrite in C if you hit performance problems, so knowing some C will let you squeeze about an order of magnitude of performance out of things. Plus, you can start to understand drivers for your hardware here.
Java is less about the language and more about the IDEs. With the possible exception of Smalltalk, Java has the best IDEs and refactoring software. This is the kind of thing that most languages should have, but don't.
Anyway, this is kind of just a menu, but if you learn three or four of these, you'll be well on your way to deciding which one suits your style.
Excellent list, and pretty much precisely what I would have posted with a few very minor tweaks: Ruby and Python are nearly interchangeable. Time is limited, so have a look at both and pick which one you like. Tcl is also a neat language in some ways - it's even better for DSL's than Ruby is, and has the lisp like property that you can create your own control structures.
Anyway, jaggederest's list is pretty much the list to learn if you want a broad overview.
"Haskell enables code reuse by not allowing side effects"
As an onlooker, I wonder: is reuse in Haskell fundamentally better than reuse in another language where the programmer avoids (or clusters) side-effects?
Well, if you avoid side effects assiduously enough, other languages can certainly have that sort of purity.
However, you have to remember, avoiding side effects is what enables lazy evaluation, which is a huge gain in terms of performance. If you're not restricting side effects, you can't default to lazy evaluation.
True... And not having lazy evaluation encourages one to write Matrix.CalculateDeterminant() rather than Matrix.determinant, as it should be. But I don't think that has to do with reuse.
Sorry, but I think that is complete bullshit. Why should some beginner start with Lisp and Haskell? He should start with something that is useful for him, that is, he should consider what he wants to do, pick a suitable programming language and get started.
Nothing against LISP, but if he was into Web programming for instance, I think it would be a bad choice. Maybe an experienced programmer could leverage the power of LISP for that task, but a beginner needs good documentation, examples to look at, a community to ask when he is stuck etc. I don't think LISP would be top of the list in those categories.
I may have misinterpreted what he wanted, but if you're asking 'how do I learn to hack', it's a whole different question than 'how do I learn to write mediocre web applications'
If your goal is to learn to build rails sites, start with rails; however, if your goal is to be good at programming and subsequently be able to build things that other people can't, in the sense of PG's hacker advantage, then you should learn to hack, not build rails apps.
The value of learning all those different languages is not that they're immediately and obviously useful. The value is that each one has a different set of tradeoffs and assumptions, and being fluent in all of them will teach you how to think more flexibly.
Sure, a beginner should use a language where he gets feedback and support. But a beginner who aspires to be a real programmer rather than a 9 to 5 coder will need a much broader base of experience than he can get by only working in one or two languages, and understanding that sooner rather than later is key.
I agree with this list - completely in spirit, though I'd probably recommend different languages in a few places - but I'd also recommend at least playing with a couple of "industry-standard" programming languages.
Playing with C++, for instance, especially after having used C and Java, will give you a better understanding of what not to do. And if you play with Objective-C for a while too, you'll see two ways of handling object orientation that are dramatically different: what seems like a minor difference makes for drastically different expressiveness and flexibility.
I'd also recommend picking up Perl, for a different understanding of what not to do. Ruby is at its core a reimplementation of the good parts of Perl, with inspiration from Python and Lisp, and it hits a very sweet spot as a result; Perl has a lot of good parts, but it has a lot of warts that seemed like a good idea at the time and have been preserved for backwards compatibility.
And one of the things that I've noticed is that Real Programming focuses on interfaces in a way that toy programs don't: in web programming, for instance, you're more constrained by the browser-CGI-server interface than anything else. In programming for platforms with GUIs, the learning curve is not the language you use but the API to the window system.
But, shouldn't we be asking the poster "why"? If the "why" is because he wants to be good at programming, then I would suggest that he first does some light c, a tiny bit of assembly, and a get a basic understanding of FP languages and the insanity of advanced OO in java.
In the end though, be sure you are using Python. Heck, even if you get bored along the way, throw some python in.
A [Warning] though: python will spoil you. Good luck going back to a more verbose, rigid language, should you be forced to.
Now, you're going to hear a lot about how wonderful LISP (etc, etc) is, but remember that almost every _real_ application is in C (Unix), C++ (games, other desktop apps), or Java (50 million goddawful enterprise backends).
That might be true of "almost every _real_" desktop application, although on my Linux install, I have a healthy amount of Python and Perl programs. As for quickly prototyped web applications, I think that Lisp, Python, Perl, and Ruby far outnumber Java and C/C++ (with Java far outnumbering C/C++).
I'd rephrase the question slightly and ask, 'what problems should I work on?' and 'how can the language(s) I use solve them'. This is one reason why lisp is a compelling choice. You can create your own sub-languages to solve any particular problem.
But for lots of reasons lisp may not be suitable. There are lots of other languages to choose so pick the ones that suit solving different problems. There is not one "universal programming hammer" (though lisp is pretty close) but an array to choose from that may suit different types of problems.
While we're on the topic, PG mentions in one of his essays a few languages with a "reputation for succintness": Forth, Joy, Icon. They are all tiny blips on my radar, popping up once every year in some obscure article. Does anybody have experience with them, and are they worth learning? (Forth is already covered on this page)
I learnt to program by writing a Forth compiler in assembler (Dad taught me). It was a superb way to learn.
One of Forth's strengths is its ultra-simple syntax. If you thought Lisp had little syntax, think again. Forth is just tokens and whitespace. You can write a compiler than can compile itself in a few screenfuls of Forth (and I'm not talking about eval).
Forth is obscure but beautiful. It's reflective, meaning you can write code that writes code (macros). Also like Lisp, you can easily roll your own control structures or add an OOP interface. But it does lack good libraries and a decent-sized user base.
I have just started poking with forth, after seeing some network card firmware source written in it.
One of the most interesting things, to me, was the built-in disassembler: if you ask 'how is this word defined', and it's not defined in the current environment, it'll go disassemble the binary and show you that.
Pretty insane, if you think about having to write software to interface with old / undocumented / closed source libraries.
Oh yes, and Forth has an elegant solution to Paul Graham's "accumulator generator" problem (though Forth isn't dynamically typed, so it only works for integers):
Instead of learning C or C++ you may consider D which will enable you to learn more about actual programming and less about the idiosyncrasies of C/C++.
I agree with the point about C. Most of my class assignments have to be programmed in C/C++ or Java. Out of those three, I usually end up choosing C, because it is not nearly as weighed down with syntax soup as Java and C++ are. So I don't really think of C as being idiosyncratic, either. It is somewhat close to the hardware, and I can't really think of much of anything that is in there without good reason.
On the contrary, C is excellently designed for its intended purpose: as a language for writing UNIX. If that's what you're doing, C is the ideal choice. If you're using it for something else, you're misusing it.
Well, most languages use C for their FFI so you're almost stuck with that. You can still use D, since it can call C functions transparently. Though, if I were designing a high-level language and wanted it to be able to call a fast lower-level one, I might choose Forth or OCaml. Once it matures a bit, I might change my answer to Fortress.
If you take a serious look at the constraints under which C was developed, the systems it was to be used on, and the problems it was intended as a solution to, you will see that it is most excellently designed.
Unfortunately for C, the constraints have changed, systems are orders of magnitude more powerful, and people have attempted to use C for many things it was not well-suited to.
50 comments
[ 0.26 ms ] story [ 277 ms ] threadIf you are going to learn a language, learn the most powerful and efficient language you can find so that you can reach your goals faster. As far as I can tell, until ARC comes out, that language is Lisp. A lot of people complain about the lack of Lisp open source out there, but in fact, our application is loaded with great open source Lisp libraries. See: http://news.ycombinator.com/comments?id=20010 http://news.ycombinator.com/comments?id=12619 http://www.google.com/search?q=site%3Aycombinator.com+lisp http://www.cliki.net/index http://common-lisp.net/
Anyways, www.hacketyhack.com is a great integrated IDE for learning the syntax of ruby.
You probably meant languages that are biased primarily towards functional programming, as opposed to others where FP is not the dominant paradigm. You have to specify that much if you are going to include the Lisps but leave Python out.
The key is to learn best practices of whatever language you choose. Don't learn bad habits. Read the authoritative books and don't take short-cuts. Don't be the guy writing code people cry at having to maintain. Avoid "cargo cult" programming, where you just paste code you find into your programs without fully understanding it. I recommend never pasting at all in fact. At the very least re-type everything as you're learning and try to understand it as best you can.
You can safely skip haskell, lisp, prolog, and all those languages you will never get friends to help you with, many books to read, or libraries to leverage. At least until you've got enough experience to be mostly independent of assistance.
With the use of best practices it doesn't really matter if you choose: Ruby, Perl, Python, or PHP. I'd ignore Java because it has so many training wheels, and the others don't. These can all work extremely well for web development and anyone who says different is selling something. The Truth™ is that Perl5 is the best and Perl6 will make them all obsolete :-)
We almost never use OO in our Perl codebase, except where bolting on OO makes a lot of sense (specifically, the UI functions, some CPAN modules that have a more natural OO interface), but in the Ruby code I've written it's all objects and it never feels forced or bolted on. Partly, it's the tasks we're doing where functional programming makes more sense, and partly it's due to having a large codebase that pre-dates Perl 5. Oh, yeah, we also have a huge swath of disparate data being passed around amongst different systems and services, and it's very natural to pass them around as arrays and treat them similarly to lists in lisp. map, grep, shift/unshift, and pop/push get a lot of use in our code. I'm pretty certain we'd do it differently in Python and we'd probably do it differently in Ruby. It'd probably take quite a bit more code in either of those languages, but it might be more readable on first (and second) glance.
Perl 6 will change some of our practices (in three or four years when Perl 6 is wide-spread, anyway), but not all of them. Objects will be beautiful in Perl 6, so we won't avoid them, and argument passing will be much cleaner (right now we pass around refs to arrays a lot, which is somewhat fragile when API changes happen), so those things will change, but our treatment of data will probably remain similar.
So, I agree with you about Ruby syntax. It looks very similar, and is very comfortable to me, as a long time perl coder. But when you actually start building things, the comfortable paths diverge quite a bit.
I think lisp will be adequately enunciated, so I'll move on to the others
Haskell is a lazy, strongly-typed functional language. It's syntax is very close to mathematical notation, and it enables code reuse by not allowing side effects. It'll teach you to think in actual algorithms, where most languages teach you to think about how to implement those algorithms.
Prolog is a logic language. It'll teach you logic, and some of the fundamental ideas from that field. Backtracking search, unification, and other interesting ideas.
Forth is a reverse-polish-notation stack language that is very 'close to the metal' and yet a higher order language than C. Forth will teach you more about the workings of a computer than anything but assembler, and it won't break your soul like assembler might.
Erlang is strict strongly-typed functional language that is all about concurrency. Right now it's probably the best language to write highly concurrent applications in, and, as it turns out, most of the internet can be made highly concurrent.
Smalltalk is the mother of all object oriented languages, and shares with lisp the interesting concept of a running image. In smalltalk, everything you do is in a live instance of an image, and to deploy, you simply move the instance over and run it on the server. This also one of the first languages to have an effective refactoring browser.
Python is a dynamic object-oriented language that incorporates features from a lot of previous languages. It's got some interesting things and a fairly nice syntax. Take a look at TurboGears, Pylon, and Django
Ruby is a dynamic object-oriented language (lisp + perl) that is (like lisp) all about metaprogramming. Ruby has also got an interesting framework that is becoming notorious, Rails, which makes OR mapping and quite a few other things brain-dead easy. If you get into the internals of rails, you'll learn a lot about metaprogramming.
C is The Language. If it has to be fast, small, and close to the metal, C is the go to language (no pun intended) There are a lot of situations where you'll end up needing to rewrite in C if you hit performance problems, so knowing some C will let you squeeze about an order of magnitude of performance out of things. Plus, you can start to understand drivers for your hardware here.
Java is less about the language and more about the IDEs. With the possible exception of Smalltalk, Java has the best IDEs and refactoring software. This is the kind of thing that most languages should have, but don't.
Anyway, this is kind of just a menu, but if you learn three or four of these, you'll be well on your way to deciding which one suits your style.
Anyway, jaggederest's list is pretty much the list to learn if you want a broad overview.
As an onlooker, I wonder: is reuse in Haskell fundamentally better than reuse in another language where the programmer avoids (or clusters) side-effects?
However, you have to remember, avoiding side effects is what enables lazy evaluation, which is a huge gain in terms of performance. If you're not restricting side effects, you can't default to lazy evaluation.
Nothing against LISP, but if he was into Web programming for instance, I think it would be a bad choice. Maybe an experienced programmer could leverage the power of LISP for that task, but a beginner needs good documentation, examples to look at, a community to ask when he is stuck etc. I don't think LISP would be top of the list in those categories.
If your goal is to learn to build rails sites, start with rails; however, if your goal is to be good at programming and subsequently be able to build things that other people can't, in the sense of PG's hacker advantage, then you should learn to hack, not build rails apps.
Sure, a beginner should use a language where he gets feedback and support. But a beginner who aspires to be a real programmer rather than a 9 to 5 coder will need a much broader base of experience than he can get by only working in one or two languages, and understanding that sooner rather than later is key.
Playing with C++, for instance, especially after having used C and Java, will give you a better understanding of what not to do. And if you play with Objective-C for a while too, you'll see two ways of handling object orientation that are dramatically different: what seems like a minor difference makes for drastically different expressiveness and flexibility.
I'd also recommend picking up Perl, for a different understanding of what not to do. Ruby is at its core a reimplementation of the good parts of Perl, with inspiration from Python and Lisp, and it hits a very sweet spot as a result; Perl has a lot of good parts, but it has a lot of warts that seemed like a good idea at the time and have been preserved for backwards compatibility.
And one of the things that I've noticed is that Real Programming focuses on interfaces in a way that toy programs don't: in web programming, for instance, you're more constrained by the browser-CGI-server interface than anything else. In programming for platforms with GUIs, the learning curve is not the language you use but the API to the window system.
But, shouldn't we be asking the poster "why"? If the "why" is because he wants to be good at programming, then I would suggest that he first does some light c, a tiny bit of assembly, and a get a basic understanding of FP languages and the insanity of advanced OO in java.
In the end though, be sure you are using Python. Heck, even if you get bored along the way, throw some python in.
A [Warning] though: python will spoil you. Good luck going back to a more verbose, rigid language, should you be forced to.
You will get a taste of all these languages/paradigms, and in addition, others like concurrent programming etc.
http://www.amazon.com/Concepts-Techniques-Models-Computer-Programming/dp/0262220695
I'd rephrase the question slightly and ask, 'what problems should I work on?' and 'how can the language(s) I use solve them'. This is one reason why lisp is a compelling choice. You can create your own sub-languages to solve any particular problem.
But for lots of reasons lisp may not be suitable. There are lots of other languages to choose so pick the ones that suit solving different problems. There is not one "universal programming hammer" (though lisp is pretty close) but an array to choose from that may suit different types of problems.
esr in his faqto (faq + howto) recommends python, c/cpp, java, perl and lisp. Each language chosen for their abilities to solve different types of problems ~ http://www.catb.org/~esr/faqs/hacker-howto.html#skills1
Tall order? Take too long? Then read on with Norvig and 'Teach yourself programming in 10 years' ~ http://www.norvig.com/21-days.html
so that you'll be able to pick the right tool for the job (nobody ever asks, "which should I learn,the hammer or the screwdriver?")
One of Forth's strengths is its ultra-simple syntax. If you thought Lisp had little syntax, think again. Forth is just tokens and whitespace. You can write a compiler than can compile itself in a few screenfuls of Forth (and I'm not talking about eval).
Forth is obscure but beautiful. It's reflective, meaning you can write code that writes code (macros). Also like Lisp, you can easily roll your own control structures or add an OOP interface. But it does lack good libraries and a decent-sized user base.
One of the most interesting things, to me, was the built-in disassembler: if you ask 'how is this word defined', and it's not defined in the current environment, it'll go disassemble the binary and show you that.
Pretty insane, if you think about having to write software to interface with old / undocumented / closed source libraries.
: accgen create , does tuck +! @ ;
From comp.lang.forth: http://groups.google.com/group/comp.lang.forth/msg/f06370fed978abff?dmode=source
Unfortunately for C, the constraints have changed, systems are orders of magnitude more powerful, and people have attempted to use C for many things it was not well-suited to.