Most programmers are aware of two type systems, static and dynamic. This distinction is important, however it's not complete. Sometimes these two systems are called strong and weak, but these terms are also used to describe other differences in type systems, as we'll soon see, so to avoid confusion, they should be avoided when discussing static and dynamic type systems.
The difference between these two systems is often claimed to be whether or not
you have to explicitly label your variables with a type, e.g. :int foo = 7;: in
C as opposed to just foo
7;= in Perl. While this is commonly the case, and
serves as a fairly useful visual clue, it is not a very accurate description.
In fact, we will look at statically typed languages that do not require
variables to be labeled with their type.
In a statically typed language, such as C, each variable is of a single type over its entire lifespan. Dynamically typed languages do not have this restriction. For example, in Perl (a dynamically typed language) you can write:
foo = 7; foo = "seven";
with no problem. In a statically typed language you would need to store these values in separate variables because one is an integer, and the other is a string.
If this is the case, what is the benefit of statically typed languages that can counter the development speed and flexibility of the dynamic approach? There are two things, compile-time type checking and runtime speed. With a statically typed language, the compiler can usually (we'll come to the exception in a bit) determine if an assignment is legal. If it's not, an error will be thrown, and it must be fixed before the program can be compiled. In the example above, if you later passed :foo: to a function that expected an integer, you wouldn't discover the error until you ran the program. And then possibly only because of an odd result, rather than an error message.
Since the compiler can do all of the type mapping at compile-time, then, that is less work it has to do at runtime, hopefully providing some speed improvement.
Static type systems can be further divided into strong and weak type systems (the ambiguous terms mentioned above). Weak systems have loopholes, strong ones do not.
What is a loophole? It's a way to get around the type system. In C, that's :void*:, in Java it's casting in general. It's anything that prevents a type-check from happening until run-time.
You might ask which languages don't have loopholes. To a lot of programmers out there, casting seems necessary. However, plenty of languages get along without casting. Eiffel is one of them. It is strongly typed, and (because of the lack of shared libraries) can even allow covariant1 parameters in methods.
If languages can exist without these loopholes, why have loopholes at all?
Strongly typed languages offer us another benefit. Since the system is closed and loophole-free, the computer can do a bit more of the work for us. There is a set of algorithms called type inference algorithms. This bit of magic means that, just as in dynamic languages, we no longer have to use type labels on variables. The compiler will look at the code and determine what all the types have to be. Strong type systems that have this property are called latent, those that don't are called manifest.
At this point we have to take another look at dynamically typed languages. Now that we can offer that same outward appearance, what are the actual differences between a latently typed language and a dynamically typed one?
Dynamically typed languages still offer more flexibility in the sense that a variable's type can change over the course of a program. Even though you're not specifying the type explicity, the compiler still gives it one specific type for the duration of the program. Considering all the work the compiler is doing now (not only to reduce runtime, but also to bring development time closer to that of dynamically typed languages), it could have slowed down considerably.
If you look at the final possibilities, you see that there are only four type systems actually available -- dynamic, latent, manifest, and weak. The last three imply static, and latent and manifest also imply strong. By using these four labels, we can discuss them without confusion, and use them to decide which qualities are most important for a given project.