wnoise comments on Open Thread: March 2010 - Less Wrong
You are viewing a comment permalink. View the original post to see all comments and the full post content.
You are viewing a comment permalink. View the original post to see all comments and the full post content.
Comments (658)
Personally, I'm a big fan of Haskell. It will make your brain hurt, but that's part of the point -- it's very good at easily creating and using mathematically sound abstractions. I'm not a big fan of Lua, though it's a perfectly reasonable choice for its niche of embeddable scripting language. I have no experience with Processing. The most commonly recommended starting language is python, and it's not a bad choice at all.
Toss in another vote for Haskell. It was my first language (and back before Real World Haskell was written); I'm happy with that choice - there were difficult patches, but they came with better understanding.
Thanks, I didn't know about Haskell, sounds great. Open source and all. I think you already convinced me.
I wouldn't recommend Haskell as a first language. I'm a fan of Haskell, and the idea of learning Haskell first is certainly intriguing, but it's hard to learn, hard to wrap your head around sometimes, and the documentation is usually written for people who are at least computer science grad student level. I'm not saying it's necessarily a bad idea to start with Haskell, but I think you'd have a much easier time getting started with Python.
Python is open source, thoroughly pleasant, widely used and well-supported, and is a remarkably easy language to learn and use, without being a "training wheels" language. I would start with Python, then learn C and Lisp and Haskell. Learn those four, and you will definitely have achieved your goal of learning to program.
And above all, write code. This should go without saying, but you'd be amazed how many people think that learning to program consists mostly of learning a bunch of syntax.
I have to disagree on Python; I think consistency and minimalism are the most important things in an "introductory" language, if the goal is to learn the field, rather than just getting as quickly as possible to solving well-understood tasks. Python is better than many, but has too many awkward bits that people who already know programming don't think about.
I'd lean toward either C (for learning the "pushing electrons around silicon" end of things) or Scheme (for learning the "abstract conceptual elegance" end of things). It helps that both have excellent learning materials available.
Haskell is a good choice for someone with a strong math background (and I mean serious abstract math, not simplistic glorified arithmetic like, say, calculus) or someone who already knows some "mainstream" programming and wants to stretch their brain.
You make some good points, but I still disagree with you. For someone who's trying to learn to program, I believe that the primary goal should be getting quickly to the point where you can solve well-understood tasks. I've always thought that the quickest way to learn programming was to do programming, and until you've been doing it for a while, you won't understand it.
Well, I admit that my thoughts are colored somewhat by an impression--acquired by having made a living from programming for some years--that there are plenty of people who have been doing it for quite a while without, in fact, having any understanding whatsoever. Observe also the abysmal state of affairs regarding the expected quality of software; I marvel that anyone has the audacity to use the phrase "software engineer" with a straight face! But I'll leave it at that, lest I start quoting Dijkstra.
Back on topic, I do agree that being able to start doing things quickly--both in terms of producing interesting results and getting rapid feedback--is important, but not the most important thing.
I want to achieve an understanding of the basics without necessarily being able to be a productive programmer. I want to get a grasp of the underlying nature of computer science, not being able to mechanical write and parse code to solve certain problems. The big picture and underlying nature is what I'm looking for.
I agree that many people do not understand, they really only learnt how to mechanical use something. How much does the average person know about how one of our simplest tools work, the knife? What does it mean to cut something? What does the act of cutting accomplish? How does it work?
We all know how to use this particular tool. We think it is obvious, thus we do not contemplate it any further. But most of us have no idea what actually physically happens. We are ignorant of the underlying mechanisms for that we think we understand. We are quick to conclude that there is nothing more to learn here. But there is deep knowledge to be found in what might superficially appear to be simple and obvious.
Then you do not, in fact, need to learn to program. You need an actual CS text, covering finite automata, pushdown machines, Turing machines, etc. Learning to program will illustrate and fix these concepts more closely, and is a good general skill to have.
Recommendations on the above? Books, essays...
Sipser's Introduction to the Theory of Computation is a tiny little book with a lot crammed in. It's also quite expensive, and advanced enough to make most CS students hate it. I have to recommend it because I adore it, but why start there, when you can start right now for free on wikipedia? If you like it, look at the references, and think about buying a used or international copy of one book or another.
I echo the reverent tones of RobinZ and wnoise when it comes to The Art of Computer Programming. Those volumes are more broadly applicable, even more expensive, and even more intense. They make an amazing gift for that computer scientist in your life, but I wouldn't recommend them as a starting point.
Elsewhere wnoise said that SICP and Knuth were computer science, but additional suggestions would be nice.
I, unfortunately, am merely an engineer with a little BASIC and MATLAB experience, but if it is computer science you are interested in, rather than coding, count this as another vote for SICP. Kernighan and Ritchie is also spoken of in reverent tones (edit: but as a manual for C, not an introductory book - see below), as is The Art of Computer Programming by Knuth.
I have physically seen these books, but not studied any of them - I'm just communicating a secondhand impression of the conventional wisdom. Weight accordingly.
Kernighan and Ritchie is a fine book, with crystal clear writing. But I tend to think of it as "C for experienced programmers", not "learn programming through C".
TAoCP is "learn computer science", which I think is rather different than learning programming. Again, a fine book, but not quite on target initially.
I've only flipped through SICP, so I have little to say.
TAoCP and SICP are probably both computer science - I recommended those particularly as being computer science books, rather than elementary programming. I'll take your word on Kernighan and Ritchie, though - put that one off until you want to learn C, then.
Merely an engineer? I've failed to acquire a leaving certificate of the lowest kind of school we have here in Germany.
Thanks for the hint at Knuth, though I already came across his work yesterday. Kernighan and Ritchie are new to me. SICP is officially on my must-read list now.
A mechanical engineering degree is barely a qualification in the field of computer programming, and not at all in the field of computer science. What little knowledge I have I acquired primarily through having a very savvy father and secondarily through recreational computer programming in BASIC et al. The programming experience is less important than the education, I wager.
Bear in mind that I'm not terribly familiar with most modern programming languages, but it sounds to me like what you want to do is learn some form of Basic, where very little is handled for you by built-in abilities of the language. (There are languages that handle even less for you, but those really aren't for beginners.) I'd suggest also learning a bit of some more modern language as well, so that you can follow conversations about concepts that Basic doesn't cover.
'Follow conversations', indeed. That's what I mean. Being able to grasp concepts that involve 'symbolic computation' and information processing by means of formal language. I don't aim at actively taking part in productive programming. I don't want to become a poet, I want to be able to appreciate poetry, perceive its beauty.
Take English as an example. Only a few years ago I seriously started to learn English. Before I could merely chat while playing computer games LOL. Now I can read and understand essays by Eliezer Yudkowsky. Though I cannot write the like myself, English opened up this whole new world of lore for me.
"It is practically impossible to teach good programming to students that have had a prior exposure to BASIC: as potential programmers they are mentally mutilated beyond hope of regeneration." --Edsger W Dijkstra.
More modern versions aren't that bad, and it's not quite fair to tar them with the same brush, but I still wouldn't recommend learning any of them for their own sake. If there is a need (like modifying an existing codebase), then by all means do.
Dijkstra's quote is amusing, but out of date. The only modern version anyone uses is VB.NET, which isn't actually a bad language at all. On the other hand, it also lacks much of the "easy to pick up and experiment with" aspect that the old BASICs had; in that regard, something like Ruby or Python makes more sense for a beginner.
Yeah, you won't be able to be very productive regarding bottom-up groundwork. But you'll be able to look into existing works and gain insights. Even if you forgot a lot, something will be stuck and help you to pursue a top-down approach. You'll be able to look into existing code, edit it and regain or learn new and lost knowledge more quickly.
Agree with where you place Python, Scheme and Haskell. But I don't recommend C. Don't waste time there until you already know how to program well.
Given a choice on what I would begin with if I had my time again I would go with Scheme, since it teaches the most general programming skills, which will carry over to whichever language you choose (and to your thinking in general.) Then I would probably move on to Ruby, so that I had, you know, a language that people actually use and create libraries for.
C is good for learning about how the machine really works. Better would be assembly of some sort, but C has better tool support. Given more recent comments, though I don't think that's really what XiXiDu is looking for.
Agree on where C is useful and got the same impression about the applicability to XiXiDu's (where on earth does that name come from?!?) goals.
I'm interested in where you would put C++ in this picture. It gives a thorough understanding of how the machine works, in particular when used for OO programming. I suppose it doesn't meet your 'minimalist' ideal but does have the advantage that mastering it will give you other abstract proficiencies that more restricted languages will not. Knowing how and when to use templates, multiple inheritance or the combination thereof is handy, even now that I've converted to primarily using a language that relies on duck-typing.
"Actually I made up the term "object-oriented", and I can tell you I did not have C++ in mind." -- Alan Kay
C++ is the best example of what I would encourage beginners to avoid. In fact I would encourage veterans to avoid it as well; anyone who can't prepare an impromptu 20k-word essay on why using C++ is a bad idea should under no circumstances consider using the language.
C++ is an ill-considered, ad hoc mixture of conflicting, half-implemented ideas that borrows more problems than advantages:
I could elaborate further, but it's too depressing to think about. For understanding the machine, stick with C. For learning OOP or metaprogramming, better to find a language that actually does it right. Smalltalk is kind of the canonical "real" OO language, but I'd probably point people toward Ruby as a starting point (as a bonus, it also has some fun metaprogramming facilities).
ETA: Well, that came out awkwardly verbose. Apologies.
I'm sure I could manage 1k before I considered the point settled and moved on to a language that isn't a decades old hack. That said, many of the languages (Java, .NET) that seek to work around the problems in C++ do so extremely poorly and inhibit understanding of the way the relevant abstractions could be useful. The addition of mechanisms for genericity to both of those of course eliminates much of that problem. I must add that many of the objections I have to using C++ also apply to C, where complexity based problems are obviously excluded. Similarly, any reasons I would actually suggest C is worth learning apply to C++ too. If you really must learn how things work at the bare fundamentals then C++ will give you that over a broader area of nuts and bolts.
This is the one point I disagree with, and I do so both on the assertion 'almost uniformly' and also the concept itself. As far as experts in Object Oriented programming goes Bertrand Myers is considered an expert, and his book 'Object Oriented Software Construction' is extremely popular. After using Eiffel for a while it becomes clear that any problems with multiple inheritance are a problem of implementation and poor language design and not inherent to the mechanism. In fact, (similar, inheritance based OO) languages that forbid multiple inheritance end up creating all sorts of idioms and language kludges to work around the arbitrary restriction.
Even while using Ruby (and the flexibility of duck-typing) I have discovered that the limitation to single inheritance sometimes requires inelegant work-arounds. Sometimes objects just are more than one type.
Indeed. I keep meaning to invent a new programming paradigm in recognition of that basic fact about macroscopic reality. Haven't gotten around to it yet.
Seriously? All my objections to C++ come from its complexity. C is like a crystal. C++ is like a warty tumor growing on a crystal.
This argues for interfaces, not multiple implementation inheritance. And implementation inheritance can easily be emulated by containment and method forwarding, though yes, having a shortcut for forwarding these methods can be very convenient. Of course, that's trivial in Smalltalk or Objective-C...
The hard part that no language has a good solution for are objects which can be the same type two (or more) different ways.
Using C is, at times, a necessary evil, when interacting directly with the hardware is the only option. I remain unconvinced that C++ has anything to offer in these cases; and to the extent that C++ provides abstractions, I contend that it inhibits understanding and instills bad habits more than it enlightens, and that spending some time with C and some with a reasonably civilized language would teach far more than spending the entire time with C++.
Java and C# are somewhat more tolerable for practical use, but both are dull, obtuse languages that I wouldn't suggest for learning purposes, either.
Well, the problem isn't really multiple inheritance itself, it's the misguided conflation of at least three distinct issues: ad-hoc polymorphism, behavioral subtyping, and compositional code reuse.
Ad-hoc polymorphism basically means picking what code to use (potentially at runtime) based on the type of the argument; this is what many people seem to think about the most in OOP, but it doesn't really need to involve inheritance hierarchies; in fact overlap tends to confuse matters (we've all seen trick questions about "okay, which method will this call?"). Something closer to a simple type predicate, like the interfaces in Google's Go language or like Haskell's type classes, is much less painful here. Or of course duck typing, if static type-checking isn't your thing.
Compositional code reuse in objects--what I meant by "implementation inheritance"--also has no particular reason to be hierarchical at all, and the problem is much better solved by techniques like mixins in Ruby; importing desired bits of functionality into an object, rather than muddying type relationships with implementation details.
The place where an inheritance hierarchy actually makes sense is in behavioral subtyping: the fabled is-a relationship, which essentially declares that one class is capable of standing in for another, indistinguishable to the code using it (cf. the Liskov Substitution Principle). This generally requires strict interface specification, as in Design by Contract. Most OO languages completely screw this up, of course, violating the LSP all over the place.
Note that "multiple inheritance" makes sense for all three: a type can easily have multiple interfaces for run-time dispatch, integrate with multiple implementation components, and be a subtype of multiple other types that are neither subtypes of each other. The reason why it's generally a terrible idea in practice is that most languages conflate all of these issues, which is bad enough on its own, but multiple inheritance exacerbates the pain dramatically because rarely do the three issues suggest the same set of "parent" types.
Consider the following types:
The generic tree and list types are both abstract containers; say they both implement using a projection function to transform every element from type A to some type B, but leaving the overall structure unchanged. Both can declare this as an interface, but there's no shared implementation or obvious subtyping relationship.
The text strings can't implement the above interface (because they're not parameterized with a generic type), but both could happily reuse the implementation of the generic list; they aren't subtypes of the list, though, because it's mutable.
The immutable length-limited string, however, is a subtype of the regular string; any function taking a string of arbitrary length can obviously take one of a limited length.
Now imagine trying to cram that into a class hierarchy in a normal language without painful contortions or breaking the LSP.
I put C++ as a "learn only if needed language". It's extremely large and complicated, perhaps even baroque. Any large program uses a slightly different dialect of C++ given by which features the writers are willing to use, and which are considered too dangerous.
Yeah, C is probably mandatory if you want to be serious with computer programming. Thanks for mentioning Scheme, haven't heard about it before...
Haskell sounds really difficult. But the more I hear how hard it is, the more intrigued I am.
Thanks, I'll sure get into those languages. But I think I'll just try and see if I can get into Haskell first. I'm intrigued after reading the introduction.
If I get struck, I'll the route you mentioned.