Anders Hejlsberg recently gave a good talk on “The future of programming languages”. He says future PLs should be more declarative, dynamic, and concurrent.
A declarative language is one that describes intent, while leaving the means of execution up to the computer. This is illustrated by domain-specific languages (DSLs). For example, in SQL you describe what you want, but the DB decides how to get the data efficiently. He uses Fowler’s term for internal vs. external DSLs. SQL is an external DSL because it is a standalone language. LINQ is internal because it’s embedded (my preferred term) in a host language (C#). He’s also fond of functional programming because he believes — incorrectly — that it is a more declarative language. I think FP people claim that it looks like a declarative language, but you still have to explain how to do stuff. Prolog and SQL are declarative languages, not F# or Haskell.
For dynamic languages, he seems to be looking at Python and Ruby as examples, rather than more efficient languages like Smalltalk and Lisp. Thus he claims that static languages are fast and better for scaling (whatever that means). Smalltalk and Common Lisp, both 20 years old, are fast and have been used in very large systems (and so has Python). He talks about meta-programming: programs that write programs. In another interview with Guy Steele, he says supporting meta-programming would be very hard because you have to expose and manipulate the AST. Then Steele turns around and says, actually, Fortress is doing just that (as did Lisp and Scheme for 20+ years). Anders mentions that C# 4.0 should support some kind of dynamic dispatch type. Unless I can add new methods to a class at runtime (like scripting languages), I don’t see the point.
Finally, concurrency is a big, huge problem that C# and other PLs will be forced to deal with somehow. He talked about the Parallel Extensions library for .NET, which offers excellent support for data parallel programming (run F on every element in a collection). It doesn’t support the other qualities he mentions: isolation, immutability and purity. The big problem is side effects in imperative languages. The PL makes no effort to detect if you are manipulating the environment; therefore, you can easily write incorrect programs with this library. I like the idea of isolation, where you can do side-effects within your “process” bubble, but not outside it. I think Erlang-style concurrency (message passing) with a data parallel library is the good start. You get coarse- and fine-grained concurrency in one package. In fact, the compiler can optimize message sends to use continuations, transactional memory or whatever.