Dynamic is the opposite of Static, not of Explicit
I recently read a post where the author said he does not care for Ruby's dynamic typing.
When people start talking about types in programming languages, the terms fly around in a rather fast and loose manner. Here's a rather extensive and balanced discussion: the article on
Type Systems in Wikipedia.
Notice that Ruby is
dynamically typed (it's types are determined at run time and can change at run time),
strongly typed (it does not allow an operation to succeed on arguments which have the wrong type), and
type-safe (it does not allow operations or conversions which lead to erronous conditions).
(There's another school of thought about how to name the properties of type systems. More on that at the bottom.)
Proponents of
explicit types may say that Ruby is not type safe because it is possible to compile programs that contain errors which will not be detected until the program is run and the erroneous condition is detected.
Statically typed languages such as C# can detect a class of such errors at compile time. Some Ruby enthusiasts argue that they do not like the boilerplate associated with explicit typing and feel that the extra error checking does not outweigh the additional overhead.
Both arguments are mistaken. Sorry about that. If Explicit and Implicit were the issues, we could add
Type Inference to Ruby and it would have the low overhead of implicit types as well as some extra error-checking (work on Soft Typing for languages like Scheme and Erlang aims to provide compile-time checking for implicitly typed languages). However, type inference is a feature of
statically typed languages.
The trouble is that Ruby is
dynamically typed. Specifically, Ruby contains extensive
dynamic meta-programming constructs. Type inference works with statically typed languages. The compiler must be able to infer the type or set of types possible for any variable.
Consider a Ruby application that modifies classes and objects at run time. The simplest example is Ruby's built-in accessor methods:
attr_accessor :foo is a class method that actually creates two instance methods at run time,
foo and
foo=. What happens when attr_accessor is called with a
variable as its argument, like
attr_accessor my_attribute?
If the type inference engine later looks at a call such as
bar.blitz = 'bash', how does it know whether attribute_accessor was ever called with 'blitz' or :blitz as an argument? Dynamic meta-programming makes the type inference problem undecidable.
A lucid argument is that Ruby's dynamic typing makes it difficult to detect type errors statically. The
correct counter-argument is that Ruby's style of dynamic typing makes it possible to use dynamic meta-programming, such as
Ruby on Rails' ActiveRecord, not that Ruby's implicit typing is more productive.
Once you've made these arguments, you can decide for yourself whether the benefits of dynamic meta-programming do or do not outweigh the advantages of static type checking.
(Updated to use the expression "dynamic meta-programming" to distinguish features like
define_method from static meta-programming features like macro systems, courtesy of the well-informed
Lambda the Ultimate).
fin
p.s. Ward's Wiki seems to use the term static typing to mean the same thing as explicit and strong typing. I prefer that the term static means that it doesn't change. The same wiki seems to use the term dynamic typing to mean the same thing as implicit and strong typing. It includes the possibility that a program is what I would call strongly, statically and implicitly typed: the checking is done at run time but the types of variables never change. The commentary suggests the phrase semantic dynamic typing for the quality of dynamic typing that encompasses dynamic meta-programming. If you like these terms, please substitute "semantic dynamic typing" for "dynamic typing" above.p.p.s. And there's another argument that dynamic meta-programming, like macros, should be considered harmful. I'm saving my reply for a rainy day.Labels: lispy, ruby