I don't know Python yet... so I don't sit around wishing Java had features that I don't know how to use, nor do I routinely encounter problems in Java that distress me over their lack of solution. It's usually my knowledge that's at fault, after all, not Java's lack of solution. Why would I blame the language?
Learn at least one new [programming] language every year. Different languages solve the same problems in different ways. By learning several different approaches, you can help broaden your thinking and avoid getting stuck in a rut.
This is valuable advice.
Thanks to Alan Turing, we know that computationally speaking, all programming languages are equivalent. If this meant they were all practically equivalent, we'd still be programming in Assembler. We're not. Instead, the history of programming has been a long procession of different languages, some of which are still going strong, and others that have withered or been superceded.
For a general purpose programming language to gain traction, it has to solve some set of problems better than competing languages. This is true of even commonly vilified languages like Basic and COBOL (or for that matter, Java). No language emerges in a vacuum: for any language to gain a following of programmers, it must attract them from competing languages by offering them something that they need.
(Paul Graham has a presumably slightly tongue-in-cheek but quite apt characterisation of languages based on what aspects of previous languages they 'fix')
Computational equivalence means that (ignoring for the moment practical matters like being able to address specific hardware), there are no problems you can solve in language A that can't be solved in language B. Language design, however, means that how A and B solve problems can be markedly different. Without exposure to other languages, it's far too easy to be blind to the fact that just because your language of choice can solve a problem, it may not solve it in the best way.
Take, for example, the canonical example of a QuickSort in Haskell:
sort [] = []
sort (pivot:rest) = sort [y | y <- rest, y < pivot]
++ [pivot] ++
sort [y | y <- rest, y >=pivot]
If you understand Haskell, it's pretty clear that this is more elegant and expressive than the Java alternative. If you don't understand Haskell, you're more likely to have a "what the?" moment, and go back to hacking Java.
Having said that, I haven't ever programmed in Haskell (I coded in Miranda in first-year Computer Science, but haven't ever used it since). Nor, I suspect, will I soon. I contend, however, that knowing how different languages solve problems makes you a better programmer in any language. Some techniques can be adapted between languages, or can be embedded in a "little language" tailored to a particular problem domain. Even at the simplest level, knowing where your language of choice is limited helps you work around those limitations more efficiently.
The danger of learning new languages, though, is that each one increases the chance that you'll turn into one of those Internet whiners (like myself) for whom the best language for any job always seems to be the one you don't get to program in often enough to see its flaws close up.
Giv'me some Lua:
http://www.lua.org/about.html
It's always odd to find yourself quoted. Makes me uncomfortable, since I know how quote-worthy I am.
It's odd that you quote the pragmatic programmers at me, though, juxtaposed with the quote of mine you offered. I certainly don't say learning is bad (it's what I spend most of my time doing, after all!), nor do I say anything like, "Well, learning is good, but learning LANGUAGES is bad."
If that's what you got out of my statement, I'm being misread down under. I was saying I'd not learned Python yet, so therefore Python envy wasn't something I suffered from... and it wasn't a comment on whether Python was justified, or if Groovy was justified, or whether non-Java was justified.
Great post, I pretty much agree with everything. But I look at languages slightly differently: each language is designed to support a collection of special cases. They focus on certain ideas and make the expression of those ideas easier than what you would see at the assembler level. Hence an OO language special cases objects to make it easy to create and manipulate objects. A functional language has rather different special cases to make functional programming easier.
Successful languages are those which pick the special cases that have wide applicability. Unsuccesful ones are either too specific (cases that aren't widely applicable) or not enough of them.
I think you get more leverage from edge cases. Take two programmers, Fred and Barney. They both know C. They each decide to learn one new language a year for five years. Fred chooses C++, Java, Delphi, C# and Perl. Barney chooses Prolog, Forth, Smalltalk, XSLT and Scheme. At the end of the time, you can say they each know six languages, but I'd be more inclined to say that Barney now knows six distinct languages and Fred now knows six dialects of Algol. I know who Who would you expect to be able to solve programming problems more effectively?
Fred obviously. None of Barneys solutions would be effective because no-one but Barney would be able to read, understand or run them, still less care.
If everything else fails... write your own...
A post-structuralist object oriented system:
"Lua’s Story of O"
http://alt.textdrive.com/lua/19/lua-story-of-o