There are all kinds of programming languages, and they all have their strengths and weaknesses. Sometimes you want fast prototyping, sometimes you want massive scalability, sometimes you want easy availability of a large library of preexisting code, or access to a specific framework. Strong typing is useful, duck typing is useful, running on a virtual machine platform is useful, avoiding memory compaction is useful. Can we get all that stuff in one language?
Given what we know now about language design, is it possible to design a language from scratch, that would work in all those contexts? In practical terms it’s not very interesting to consider a language without also considering it’s implementation, (virtual machine, compiler, optimizer, etc) so we’re really talking about a software design for an implementation and talking about a language design at the same time. Maybe it should be called a “programming system”.
One idea I think would be interesting to explore would be whether you can get the benefits of strong typing in a language where types were optional. There’s a common rhetorical trap here that goes something like this: You have to force everyone to use strong typing, otherwise people won’t do it, and you won’t get the benefits. I’ll call that the “paternalistic fallacy”.
You want the ability to say that a module should abide by specific typing policy, and have the system enforce that. That makes it easy to use the system in different ways depending on the needs of your situation. If you just want to conjure up a quick prototype, you shouldn’t need to define lots of extra typing goop. When you want to export that code and let other people use it, and test the heck out of it, you want to change the typing regime.
Essentially all types can be thought of as an assertion that could be applied at runtime instead of compile time. Types allow the compiler to optimize in very important ways, like not doing a dynamic lookup for all methods calls. Types allow you to verify the correctness of your code, like trying to assign a floating point constant to an integer variable. In my mind, these factors boil down to optimization and assertion checking. These features are crucial to have when you need them, but they’re not always appropriate.