in reply to
Right tool for the job?
Since this question has been visited so many times from the language-to-language and programming paradigm comparison perspectives, I'll see if I can expand it in a slightly different direction. As much as the variety of coding styles (functional, logic, OO, pure recursive, etc.), programming languages have different working environments. Besides gaining knowledge of different syntax and supplied constructs (RUBY for OO, for example, or SNOBOL for pattern matching), it's also good to look at different modes of programming.
First, a good subject to explore is programming a microcontroller in assembly language. Some micros have easier programmers to use than others, like the PIC from GI and the AVR with bootstrapping FLASH from Atmel. If you can get your hands on an Atmel Butterfly demo board, you can do an incredible amount of experimenting in both hardware and firmware directions. (Available from DigiKey in single quantities for around $20.) These single-chip systems allow you to learn to appreciate the true cost of advanced programming constructs as you interleave interrupt handlers with main line code. They are so primitive, yet so powerful, that there's much to be learned there.
The whole concept of a UNIX shell is so powerful, regardless of what you might think of BASH or csh syntax, that it's well worth studying as a concrete example of interpretation at its most powerful level. Studying other parts of your OS source code, such as the scheduler, TCP/IP stack, and various daemons, are also worthwhile for your growth. Perl can be used to do various tasks, and is so used, in many UNIX systems.
Different forms of IDE and framework are also worth studying. Smalltalk has already been mentioned, and I really miss APL as the best example of an interactive calculator-style interface. I once used a really awesome window builder IDE built on top of Smalltalk (called Window Builder) that you could use to do most of a GUI-based OO app with virtually no coding except for your various extensions to the Collection classes that provide your app's data structures. Another example (though less effectively implemented) is the Microsoft VB programming system with its forms and other constructs. Many of the concepts embedded in these kinds of programming environments can enhance your programming capabilities by providing nuggets of insight.
Another form of programming to study is compiling. Not compiled programs written in C or some other set of syntax, but the compiler / translators themselves. The concepts of declaring your syntax, parsing it, creating symbol tables, etc., are full of concepts that are fundamental tools in programming. Most books in this area are dense and arcane, but you can get a lot from studying the manuals and tutorials for things like lex and yacc and Backus-Naur descriptions of the syntax of various languages.
A final area of study that I'll mention is the area of knowledge representation and pattern matching. There are many ways of approaching this (from BNF to Perl RegEx to expert system rule bases), but the fundamental concepts can help you build more readable and maintainable programs. A key concept I use in many of my programs is to study the states of a system and the rules for transitioning from one state to another. By creating rule sets and a problem-specific set of declarative and action constructs, one can create a 'little language' that makes the problem domain explicit and concrete and easily extended.
By understanding more of how your computer's software is layered and interleaved, you can make your own additions much more efficient and understandable. Many current CS courses of study that I've looked at do not make enough of an effort in this direction so that students learn to understand the methodology of embedding their program into the real machine and software system that it will run on. While it is important to understand programming abstractions thoroughly, understanding the underlying systems and plusses and minuses of various programming methodologies is crucial to making effective use of your machine to solve your problem in the best way possible.