Steven has posted 36 posts at DZone. View Full User Profile

Dynamic Typing vs Dynamic Language Explained

02.18.2008
| 22560 views |
  • submit to reddit

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!

Published at DZone with permission of its author, Steven Devijver.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Comments

Ricky Clarkson replied on Thu, 2009/04/16 - 6:51pm

It's not static typing if it's not checked statically (i.e., before the program is running).

Ittay Dror replied on Mon, 2009/12/21 - 2:09am

You can achieve the exact same effect in Ruby by checking kind_of? at the beginning of the method. You can then either throw an exception, or do different computation based on the type to acheive overloading (note: i like this approach of overloading better, as usually two overloaded methods will have a lot of common code, often resulting in defining one in terms of the other or calling a third method).

True static typing gives you two things: performaance and IDE support. Other than that, the whole compilation thing is just nuisance.  It does not catch all errors (NPE, logical errors), so you must still have testing. 

Venkat Ganesh replied on Mon, 2011/09/05 - 9:23am

Nice article, thanks. Can you think of just one application for which a software developer must employ Meta-Object Protocol implementation (MOP) say from Groovy, to solve the problem? I understand using Groovy a software developer write less code and accomplish more, which is really nice. I also understand Groovy programmers use MOP feature (XMLSlurper/Markup builder etc) to read/write from/to a xml file while a Java programmer can use the Java API for XML Processing (JAXP) library to parse, transform, validate and query XML documents. So, the end result produced either by the Java programmer or Groovy programmer, in this example is the same, while they both use different approach to solve the same set of problems. Again, the present day tools (IDE's) and library enable code completions and automatic code generations etc., it is hard to argue Java developer is at a disadvantage compared to Groovy programmer or other way around. We know Java performance is better than Groovy and one day maybe Groovy will catch up with Java in speed and for all practical purpose there will no noticeable difference in the time taken to complete a job. So, this takes us back to the question, can we think of an application/problem for which it is necessary to apply MOP technique, to solve the problem and this problem is very difficult or impossible or clumsy to solve using a static language like Java? Thanks,

Marko Milicevic replied on Mon, 2011/11/14 - 10:59am in response to: Venkat Ganesh

If you are asking a "Touring-test"-like question, "can a program be built using a MOP, that can not be build using a static language without a MOP", then the answer is no. Any program you can build with Groovy, you can also build a functional equivalent using Assembly language.

But if your question is, "Can Groovy be used to write applications that are closer to the problem specification", then i would say yes.

Groovy and meta-programming in general is a wonderful tool for helping reduce the lines of code written to solve a business problem, to reduce boiler-plate, write code that is more intentional, more declarative/spec-oriented, less action-oriented.

All of this can make someone more productive, makes apps more maintainable, and possibly lead to less errors since Groovy makes it easy to write (and encourages) automated testing, and less lines means less lines that can fail.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.