Duck Typing: this is a casual term that aliases "latent typing" or "structural typing." It means that you, in effect, specify a type by giving a subset of the methods it needs to support. I usually put it like this: "I don't care what type you really are, as long as you walk() and quack()." The "duck" comes from the phrase "if it walks like a duck, and talks like a duck, then for all intents and purposes it's a duck." Thus the actual constraints on a type are loosened, and code that you write using latent typing is more "generic" -- it works across a larger set of types. Dynamically-typed languages like Python and Ruby support latent typing, but so does C++, so latent typing is not constrained by wether the language uses static or dynamic typing. Java and C#, alas, do not support latent typing, so the result is that their generics are far less "generic" than they could be, and as much as they (especially Java) bash C++, C++ templates are a more powerful generic type mechanism than Java or C# (although C# still has some advantages over Java where generics are concerned).
Languages and libraries: I think focusing on library components is definitely a key aspect of language design. Arguably the biggest leverage we get in a language is the ability to easily reuse library components. One of the attractions of PHP, for example, is its large collection of solved problems in the form of library components.
When I was on the C++ Standards Committee, one of the stiking things I heard Bjarne Stroustrup say was something to the effect that C++ was intended to make library use easier. It did this, but it did not make library creation that much easier, and as a result the creation of libraries did not increase that much. Java actually made library creation easier, and so components were easier to create as well as use, and we saw an explosion of components (I would argue that, for some reason I haven't been able to put my finger on, I find library components in Python much more intuitive to use than Java library components; something about the way that you're encouraged to create the components makes the Java components more obscure to me, whereas I can usually drop a Python component into a program and get it doing what I want in a much shorter time).
So I would say that writing library components is simply a more difficult process, which really tests and challenges the boundaries of a language. In the first versions of Visual Basic, you couldn't create VB components using VB, which probably seemed good in theory at the time but turned out to be quite limiting. And although C++ moved the library issue forward, it didn't make it easy enough, which opened the door for Java. And Java left the door partway open for C#, etc. The uptake of these languages is driven by improved productivity, and the greatest benefits in this area are still to be found in library creation and use.
Concurrency Support: that said (and keeping in mind that I just finished the Concurrency chapter in Thinking in Java 4th edition), I think the other area where a language could have great advantage is in implementing a much better model for concurrency. This is where Heron or Nice or D could really stand out and solve a lot of problems, but as far as I can tell they are all following a kind of "decorated pthreads" (aka Java) approach to the problem, which I think is a dead end -- the concurrency problem is not subdued with such a strategey.
I understand why language designers are doing this; concurrency is hard, and "decorated pthreads" is well-understood, especially if you are draw to the low-level details as compiler writers often are. But if you really want to make a breakthrough language, I think it will be essential -- especially with multiprocessor machines becoming more common -- to come up with a more object-oriented model for concurrency, one that makes it much easier to write working concurrent programs and much harder to write broken ones. I've started a thread discussing these issues for Python, which you can find here (look for "Pythonic Concurrency"), and a number of postings include URLs for papers and implementations that describe newer thinking on the subject.
One thing that needs some emphasis: people need to design libraries as if testing mattered. Too often, if you use someone one's library, there is no easy way to write unit tests for the code that uses it.
There are many things that can and do get in the way: use of final or sealed, use of concrete classes rather than interfaces, and use of statics that can't be reset.
Languages make a difference also. Some languages have type systems which allow easy class substitution, others don't.
Exactly. Concurrency is just one place where a language can produce dramatic improvements. Testing is clearly another.
I made some suggestions for language support for unit testing in the D language that were incorporated by Walter Bright, for example, and while they helped I suspect they didn't go far enough (and as I mentioned, I don't think D's approach to concurrency is very helpful).
It would be interesting to go at a language design with testing in mind; not just support for developer testing but looking at all the things that might impede testing, as you suggest.
Although it's quite beyond me, the PyPy developers have been explicitly facilitating alternative concurrency models for some time. I have not kept up with the results of such experimentation though.
Bertrand Meyers has been writing about this same problem for awhile now. He has some ideas which he applies to Eiffel but probably could be applied to Java also. Currently he is working on creating a translator that takes his simple ideas and under the surface creating a threading program - the developer works at the higher level and the compiler takes care of the details to make it work w/ threads. You can read about it here: http://archive.eiffel.com/doc/manuals/technology/concurrency/short/page.html
For what it's worth, I keep coming back to the idea that threads are so problematic that, well, we would probably all be better off if we went to coroutines or state machines. But that's such a radical point of view, that I'm not going to mention it in public. Ooops.
Yes, I know Perl is not Python. Even so, I remember an article written by a Java programmer who lamented the extra abstraction many Java developers put into their libraries when compared to Perl programmers. Unfortunately, I can't find that articel right now.
But the moral of the story is that I would expect that Python's libraries don't use object factories as much as Java libraries do, and that by hitting the "right" abstraction level (as compared to designing so openly that any abstraction level will do), Python libraries are very useful, where Java libraries need extra configuration. I expect that, because many programmers hold that view.
I don't see duck-typing as making a whole lot of sense for writing libraries. If your library has a method that requires an object implementing walk() and quack(), the person using your library needs to know this. So you have to document it, and this is best done in a way that the compiler understands, using something like a Java interface.
The only thing that's really missing in Java is an easy way to retroactively declare a new interface for an existing class whose code you can't change. For example, it should be possible to define interfaces that are subsets of the methods in java.lang.String.
I believe Alice is based on Mozart-Oz, which uses a dataflow concurrency model that is not really new - though it is really cool. Erlang was an earlier language that has a similar concurrency model.
I've done quite a bit of work in the last two years with REALbasic which, like Objective-C, has an easy syntax for adding methods to existing classes.
This has long been touted as why Objective-C and NextStep were so powerful for library development - you don't need factories everywhere if you can extend classes rather than subclassing just to add functionality.
Note: in REALbasic this is limited to adding methods, not doing overrides. It's interesting to see how much power this relatively minor feature adds. It also makes for much more robust code - you aren't casting return variables all over the place because you've extended the original signature so the base type is acceptable.
Can you give any further details about your experiences with RealBasic -- what's been good and bad? Thanks. It's one of the tools I've thought of exploring.