"Since <i>every</i> value in a dynamic language is classified in this manner, what we are doing is agglomerating <i>all</i> of the values of the language into a single, gigantic (perhaps even extensible) <i>type</i>."<p>Yes, that's right, but you're overlooking the upside of doing things this way. What this gives us is the ability to define new types -- to extend the universal type, if you want to put it that way -- <i>at runtime</i>. No longer do we need this strict separation between compilation time and runtime; no longer do we need the compiler to bless the entire program as being type-correct before we can run any of it. This is what gives us incremental compilation, which (as I just argued elsewhere, <a href="http://news.ycombinator.com/item?id=2345424" rel="nofollow">http://news.ycombinator.com/item?id=2345424</a>) is a wonderful thing for productivity.<p>"[...] you are depriving yourself of the ability to state and enforce the invariant that the value at a particular program point must be an integer."<p>This is just false. Common Lisp implementations of the CMUCL family interpret type declarations as assertions, and under some circumstances will warn at compile time when they can't be shown to hold. Granted, not every CL implementation does this, and the ones that do don't necessarily do it as well as one would like; plus, the type system is very simple (no parametric polymorphism). Nonetheless, we have an existence proof that it's possible at least some of the time (of course, it's uncomputable in general).<p>"[...] you are imposing a serious bit of run-time overhead to represent the class itself (a tag of some sort) and to check and remove and apply the class tag on the value each time it is used."<p>For many kinds of programming, the price -- which is not as high as you suggest, anyway -- is well worth paying.<p>In particular, dynamicity is <i>necessary</i> whenever data live longer than the code manipulating them. If you want to be able to change the program arbitrarily while not losing the data you're working with, you need dynamicity. In dynamic languages, the data can remain live in the program's address space while you modify and recompile the code. With static languages, what you have to do is write the data into files, change your program, and read them back in. Ah, but when you read them in, you have to check that their contents are of the correct type: you've pushed the dynamicity to the edges of your program, <i>but it's still there</i>.<p>For this reason, database systems -- the prototypical case of long-lived data -- have to be dynamic environments, in which types (relational schemata, e.g.) can be modified without destroying the existing data.<p>So to argue -- rather arrogantly, I might add -- that dynamic languages are really static languages is to overlook an operational difference that is a commonplace to anyone who uses both.