Learning to program in a given language requires a non-trivial amount of time. This seems to be agreed upon as a good use of LessWrongers' time.
Each language may be more useful than others for particular purposes. However, like e.g. the choice of donation to a particular charity, we shouldn't expect the trade-offs of focusing on one versus another not to exist.
Suppose I know nothing about programming... And I want to make a choice about what language to pick up beyond merely what sounds cool at the time. In short I would want to spend my five minutes on the problem before jumping to a solution.
As an example of the dilemma, if I spend my time learning Scheme or Lisp, I will gain a particular kind of skill. It won't be a very directly marketable one, but it could (in theory) make me a better programmer. "Code as lists" is a powerful perspective -- and Eric S. Raymond recommends learning Lisp for this reason.
Forth (or any similar concatenative language) presents a different yet similarly powerful perspective, one which encourages extreme factorization and use of small well-considered definitions of words for frequently reused concepts.
Python encourages object oriented thinking and explicit declaration. Ruby is object oriented and complexity-hiding to the point of being almost magical.
C teaches functions and varying abstraction levels. Javascript is more about the high level abstractions.
If a newbie programmer focuses on any of these they will come out of it a different kind of programmer. If a competent programmer avoids one of these things they will avoid different kinds of costs as well as different kinds of benefits.
Is it better to focus on one path, avoiding contamination from others?
Is it better to explore several simultaneously, to make sure you don't miss the best parts?
Which one results in converting time to dollars the most quickly?
Which one most reliably converts you to a higher value programmer over a longer period of time?
What other caveats are there?
As far as I can tell, there is no such thing as a good programmer who knows only one programming language.
There just isn't. The nature of the field is that raw computation is quite alien to ordinary human thought; and that the best way to get anything even remotely resembling a reasonable grasp on it is to come at it from multiple angles.
You should know about functional abstraction, which you're not going to get very much of out of C or Perl, but you might get out of Lisp or Haskell.
You should know something about how the machine operates, which you're not going to get out of Java, Python, or Haskell, but you might get out of C, Forth, or assembly. And reading about the actual architecture you're working on. (It's easier to do this on a dinky architecture. I recommend 8-bit AVR microcontrollers.)
You should be eager to reuse other people's code to solve your problems, which you'll learn from an open-source, big-library language like Python, Perl, or Ruby, but probably not from a small, standardized language like C or Scheme.
You should learn about data structures, which you'll only get deeply if you have to implement them yourself, which is really only something you do in a CS class — but you should also learn about not reimplementing data structures that someone has already done for you better than you can do yourself. You can pick that up in any language with good data-structures libraries, like C++ with STL, Python, Haskell, etc.
You should learn about types as an expressive system and not merely a burden, which you'll get from a strongly-typed, type-inference language like Haskell, but not from a heavyweight manifest-typing language like Java or C++.
You should know how the OS works, which in most systems today you can really only get by learning C. You should know about system calls, the standard library, sockets, and so on. You should know why we don't use
gets(3)
any more.You should know about Lisp macros because there's really nothing else comparable in any other language. Template Haskell doesn't really count, and C macros especially don't count.
You should learn about parsing the traditional way; and then learn about monadic parser combinators in Haskell, because they are fucking awesome.
You should know what a buffer overflow is, what a format-string exploit is, what an SQL injection is.
You should know about relational databases. I could go on about relational databases because they are deeply misunderstood by most programmers and actually contain a wealth of hidden awesomeness; but I won't, because it would go on forever, and much smarter people like Chris Date have written it already. Suffice it to say that a relational database is not just a place to stuff variables that you want to keep around for a while; it is a place to stuff facts that you want to draw inferences from. There — that makes it sound suitably AI an' shit.
You should learn how to work with a nontrivial runtime that does things like garbage-collection, which you won't get out of C or C++ but you might get out of Lisp, Java, Python, Ruby, or Go ... if you pay attention.
You should learn about concurrency, which you can maybe get by learning about threads and the like in a language like Python, C++, or Java, but you'll probably learn better in a language like Erlang, Go, or Clojure that treats concurrency as a first-class concern.
Anyway, as should be obvious, computation is big and there is a lot to learn. But you can pretty much jump in anywhere. There's no right or wrong starting point, so long as you keep in mind that it's a starting point. Don't let anyone convince you that their personal pet language or system is all you will ever need. They're just trying to get you to join their phyg, and phygf exist at your expense.
Computing is a field that you can keep doing for a long time and still have lots to learn. This is, in fact, part of what makes it awesome.
I keep meaning to try drinking some of the relational kool-aid -- any links you'd recommend?