Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Dynamic Typing vs Dynamic Language Explained

DZone's Guide to

Dynamic Typing vs Dynamic Language Explained

The differences in dynamic language and dynamic typing explained.

· Web Dev Zone
Free Resource

Learn how to build modern digital experience apps with Crafter CMS. Download this eBook now. Brought to you in partnership with Crafter Software

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!

Crafter is a modern CMS platform for building modern websites and content-rich digital experiences. Download this eBook now. Brought to you in partnership with Crafter Software.

Topics:
ruby ,groovy ,python ,dynamic typing ,dynamic language ,web dev

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}