I think one important thing is to learn more than one language. There are a couple reasons for this, but if I had to give you just one, here is what it would be:
In most languages I know, there are certain programming techniques that are considered "difficult", "advanced" or "black magic". There are other techniques which are considered "easy", and are usually taught to beginners. What's interesting is that these techniques are not the same in each language. In fact, techniques that are considered "advanced" in one language are very often "easy" in another! Why is this? In my opinion, it's not that you have to be smarter to write code in, say, Haskell than in C++. It's that some techniques that are directly supported by the most basic language constructs in Haskell require the sophisticated use of multiple obscure language features to achieve in C++. So they get the reputation of being "hard" because when most people learn them, they're learning the obscure language features and trying to grasp the sophisticated implementation details at the same time they're trying to learn the concepts behind the technique. I don't mean to pick on C++ here: the same thing is true the other way around. (the code for DiffArray is utterly hair-raising, for instance) I also think that programmers who have learned these techniques in a language where they're "hard" sometimes have trouble separating the many implementation details from the technique itself. That can make it hard for them to implement a slightly modified version of the technique, or to recognize someone else's implementation when they run into it. If you've seen the basic idea in another language, it's a lot easier to focus on the details of how to get it done in another language, and it's easier to know when to deploy it (you might not know exactly how to do it yet, but at least you know that it will solve the problem in front of you). It's basically about getting more "tools" in your mental toolbox, so you don't end up trying to drive screws with a hammer. :-) I was avoiding naming particular techniques here, but for instance, a lot of C++ programmers avoid templates -- functions that can operate on more than one type -- because they're considered "too hard". In Haskell, *every* function can operate on multiple types; there's no special syntax required to do it. Conversely, a lot of sophisticated C++ code relies on making use of "side effects": functions that, instead of computing something, modify some pseudo-global variable. Haskell eliminates the routine use of side effects, but there are some approaches to problems that are much easier to understand in terms of side effects, even if your final implementation doesn't use them. I would advocate learning two languages early on: a lot of people invest much time and effort in just one, and then find it too difficult to learn a second. I'm not sure why this is, but my theory is that it's some combination of: (a) "baking in" a concept of how you conceive of a computer program, so that it's hard to become accustomed to / pick up a new language. (b) the fact that when you start learning a new language, you start as a beginner (or almost a beginner), which can be a frustrating experience for someone who was an expert in the language they were using before. I imagine it must be like going back to grade school to study arithmetic again. For the particular languages, I would advocate (1) a traditional imperative language such as Java, C#, Python, C++ PHP, Fortran, Ada, PL/1 ;-) etc. These are all more or less the same (modulo memory management, see below) and they're what you'll actually use for practical programming and if you want to get a paying job. (we wouldn't call it "work" if it was fun. :-) ) and at least one of (2) a Lisp descendant such as Scheme or Common Lisp. Scheme is perhaps easier to learn; Common Lisp seems to have more "stuff" to get stuff done (although IIRC, drscheme/mzscheme has a pretty good environment and set of libraries). Lisp has some "interestingly different" ideas about how a programming language can be designed, like its powerful macros, and although it looks funny, it's actually not that different from (3) one of the strongly typed "functional" languages, like O'Caml (an ML descendant) or Haskell. These are good for learning a lot of techniques I might also through Erlang in there -- from what I've heard it's a good introduction to concurrent programming. Sadly I haven't had time to learn it myself. :-( Also: if you want to become a really expert computer programmer, you really MUST become proficient in C or C++ at some point. (and when I say C++, I mean "C with objects", not "insane template library hiding everything in the computer from you", despite my love of such template libraries) They are still the only games in town when it comes to getting a handle on what's going on underneath all the other language implementations, and if you know that stuff, there are all sorts of problems you can tackle that someone whose knowledge stops at the implementation boundary won't be able to touch. However, these two languages also require you to ask the system for memory when you need to store some data, and to give it back when you're done. It might be surprising, but this turns out to be rather difficult -- in fact, until you become quite skilled with the language, most of the bugs you write will be related to memory management. And TBH, I think the main "skill" C/C++ programmers learn around memory management is how to avoid writing programs in which memory management is difficult. :-) However, it's useful to have some understanding of how this works, because memory handling can cause problems for you in higher level languages if you don't understand how it works. And, of course, because then you can do stuff that requires working in a language with manual allocation (for whatever reason). Daniel -- To UNSUBSCRIBE, email to debian-user-requ...@lists.debian.org with a subject of "unsubscribe". Trouble? Contact listmas...@lists.debian.org