Dynamic Typing vs Dynamic Language Explained
I've just finished reading a very interesting post on the virtues of static typing compared to dynamic typing. It took me some time to get my head round the Ruby, Python, OCaml and Haskell code examples. Yet I managed to draw some conclusions based in this article:
- Ruby and Python are dynamically typed languages. They don't support static typing
- OCaml and Haskell are statically typed languages. They don't support dynamic typing
- Many people are confused by the difference between dynamic typing and dynamic languages
The difference is clear enough however. VB Script (Visual Basic Script) is a dynamically typed language yet is not a dynamic language. The code below is valid VB Script (runs on windows with cscript.exe):
dim x dim y x = 1 y = 2 x = "ABC" y = "XYZ"
Ruby and Python use dynamic typing and they are also dynamic languages. Here's a code snippet that demonstrates Ruby's dynamic dispatch mechanism:
class Dummy
def method_missing(m, *args)
args[0] + args[1]
end
end
raise "Error" unless Dummy.new.test(1, 2) == 3
The test() method called on the Dummy class on line 7 is dispatched by Ruby to the method_missing() method on lines 2 to 4. Python and Groovy also support dynamic dispatch. In general, dynamic languages like Ruby, Python and Groovy have a Meta-Object Protocol or MOP.
Back to the post I mentioned at the start. The author tries to prove that static typing is superior to dynamic typing. To make his point he uses this Ruby code (there are also examples in Python, OCaml and Haskell):
def test(a, b)
a + b
end
def main()
if ARGV.length > 3
test(1, test)
else
test(1, 2)
end
end
Process.exit(main())
This code works fine when passing 0, 1, 2 or 3 arguments on the command line:
$ ruby -w -W2 t.rb; echo $? 3 $ ruby -w -W2 t.rb 0; echo $? 3 $ ruby -w -W2 t.rb 0 1; echo $? 3 $ ruby -w -W2 t.rb 0 1 2; echo $? 3
However, when passing 4 arguments on the command line the Ruby script fails:
$ ruby -w -W2 t.rb 0 1 2 3; echo $?
t.rb:7:in `test': wrong number of arguments (0 for 2) (ArgumentError)
from t.rb:7:in `main'
from t.rb:13
1
$
Based on this Ruby script the author makes the following conclusion:
As is expected from a dynamically typed language like Ruby, the error wasn’t detected until runtime. [...] Even were unit tests to be used, it is quite possible that duplicating such a scenario would be missed, and a perplexed user would be faced with an error such as the one above.
Well, you can't argue with that. He goes on with OCaml and Haskell versions of the same script. In conclusion the author says:
As we have clearly seen above, dynamically typed languages like Ruby and Python can allow for some flawed code to be written with ease. But more dangerously, it is possible for the code to run just fine, until a certain context arises upon which a runtime error occurs. [...] Thankfully, statically typed languages provide a very natural way of avoiding such problems at runtime, instead having them be caught at compile-time.
And this is where the confusion has set in firmly, by mixing dynamic typing with dynamic language. The author never mentions "dynamic language" in his post (only "dynamically typed language") yet he claims that statically typed languages detect type confusion at compile-time, hence are safer for developers to use.
Alas that's not true. It is true for statically typed, non-dynamic language like Java, C#, OCaml and Haskell. However, there's also a statically typed, dynamic language. It's called Groovy. Groovy supports both dynamic typing and static typing.
Here's a statically typed Groovy script that fails at runtime:
int x = "test"
This is the runtime error:
Caught: org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object 'test' with class 'java.lang.String' to class 'java.lang.Integer'
at typesafe.run(typesafe.groovy:1)
at typesafe.main(typesafe.groovy)
Hmm, Groovy is undeniably type safe (note however that there's no compilation error). Yet it's also a dynamic language. Here's the previous Ruby script written in Groovy:
def test(int a, int b) {
a + b
}
if (args.length > 3) {
println test(1, "test")
} else {
println test(1, 2)
}
Look at the declaration of the test() method on lines 1 to 3 and its statically typed arguments. Will this script compile? Yes. Will this script fail when 3 or less arguments are passed on the command line? No. Here's the output for 0 to 4 command line arguments:
C:\>groovy type_safe
3
C:\>groovy type_safe 0
3
C:\>groovy type_safe 0 1
3
C:\>groovy type_safe 0 1 2
3
C:\>groovy type_safe 0 1 2 3
Caught: groovy.lang.MissingMethodException: No signature of method: type_safe.test() is applicable for argument types: (java.lang.Integer, java.lang.String) values: {1, "test"}
at type_safe.run(type_safe.groovy:6)
at type_safe.main(type_safe.groovy)
C:\>
Why does this script compile when the test() method has typed arguments? The call to the test() method on line 6 is clearly incorrect!
Groovy is a dynamic language with a Meta-Object Protocol. The Groovy compiler has not way of knowing how the method call on line 6 will be dispatched. Maybe it's dispatched to the test() method declared on lines 1 to 3. But dynamic configuration at runtime can also mean the method call is dispatched elsewhere.
Groovy supports static typing, Ruby and Python don't. Because they are dynamic languages their compilers or interpreters can't know how method calls will be dispatched (this information is only available at runtime). Their Meta-Object Protocol implementations are the power of these dynamic languages.
For the Ruby and Python designers static typing support probably didn't make any sense since it can't be enforced at compile time anyway. Groovy supports static typing to support for example method and constructor overloading.
Dismissing Ruby, Python and Groovy because they don't check types at compile-time does not take into account the power of dynamic languages. I understand that non-dynamic languages are desirable for many reasons but so are dynamic languages.
Next time you hear people complain about dynamic language for their lack of static typing you'll be better informed to understand why they are complaining. Maybe they don't like dynamic languages, or they like static typing a lot. But at least you'll know there's a difference between dynamic typing and dynamic languages. And you'll also understand they probably prefer statically typed, non-dynamic languages.
Happy coding!
- Login or register to post comments
- 2646 reads
- Flag as offensive
- Printer-friendly version
(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)







Comments
Mike P replied on Tue, 2008/02/19 - 10:31pm
Groovy supports static typing, but unfortunately using static primitive types provides only a slightly slower performance than Java using boxed types. It looks like Groovy does not get the performance benefits of static primitive types as you get in Java.
Things like comparisons being done by calling methods under the hood to do it, having to re-create boxed types under the hood every time a primitive's value changes, and every method called through introspection (does it?), just obliterates Groovy's performance.
Unless these performance issues are address, I can only use Groovy where I would otherwise use something like Javascript, for some light business rules and as a glue language. It's nice to be able to have a runtime-modifyable language, which is great for development, but its performance problems keep it away from using Groovy for the deeper stuff. Beans and low level components will continue to have to be written in Java I'm afraid.
Can't Groovy get enhanced so that when the compiler knows you're doing primitive stuff, to emit primitive bytecodes, and for calling methods that are obvious, just call the method without introspection directly?
Ricky Clarkson replied on Wed, 2008/02/20 - 6:44am
Groovy is not statically typed. Those are type assertions, that are checked at runtime. For example, int i='hello' is valid Groovy code, but throws an exception.
Are you also telling me that dynamic language is a term specific to OOP? Can procedural languages be dynamic?
I put it to you that the term is vague and shouldn't be used. Enough people say "dynamic language" to mean "dynamically-typed language" that the term "dynamic language" is overloaded enough to be confusing, unless you are in a group of people who can agree on one meaning for it.
Artur Biesiadowski replied on Sat, 2008/02/23 - 7:11pm
Well, if you want to really split the hair, java as presented in Eclipse is also behaving like groovy from the point of 'static typing'. If you type
int x = "ABC";
in method, you can still run program and get the exception only when you go inside that method. Only difference is that Eclipse warns you also on compile time, but still allows you to deploy the classes which will work perfectly as long as you don't use that method.
Using wikipedia definitions of static typing:
"A programming language is said to use static typing when type checking is performed during compile-time as opposed to run-time"
groovy is not statically typed.
Groovy might be strongly typed (depending on definition of it), but it is not statically typed.
To confuse everybody even more, you can treat java as dynamic language. There is a definition of dynamic language as something which is able to create executable code on the fly. Java dynamic loading system + any of in-process assemblers/compilers fit the bill.
Ricky Clarkson replied on Sun, 2008/02/24 - 2:48am
Artur Biesiadowski replied on Sun, 2008/02/24 - 1:07pm
in response to: rickyclarkson