Static versus typing is a Ford-Chevy argument among programmers. Here’s the best comment on the subject I’ve seen lately.
Very briefly put, the Haskell [strongly, statically typed] perspective emphasizes safety, while the dynamic outlook favors flexibility. If someone had already discovered one way of thinking about types that was always best, we imagine that everyone would know about it by now.
Source: Real World Haskell.
The second sentence applies equally well to all Ford-Chevy arguments: if one alternative were uniformly better than all others, word would get out. These arguments rage because they involve comparisons along multiple (often implicit) criteria and no alternative is simultaneously better by all criteria.
The relative advantages of programming languages depend on how the languages are used. Although dynamic languages place less emphasis on safety, programs written in dynamic languages may be safer in practice than this would imply. Also, in general it is easier to reason about code written in a statically typed language. However, a programmer can easily subvert strong static typing by writing stringly typed code. Code written in well in a dynamically typed language will be easier to read than code written poorly in a statically typed language.
Comparisons of the advantages static and dynamic typing are nearly impossible. You could try to argue about what would happen “all other things being equal,” but of course all other things are never equal.
Related post: Questioning the Hawthorne effect
You’ve really never seen a better comment on the subject than one that uses the logic “I guess there’s no answer because we don’t know it by now”?
I don’t need to take a stand on the actual question of whether or not one is inherently better than the other to recognize fail logic when I see it.
sherifffruitfly: I’m not saying that there’s no answer, only that there’s no universal answer. I find it credible if someone says “I’ve found that given my personality, my experience, my skills, and the kinds of problems I work on, dynamic typing works better for me.” As statements get more general, I get more skeptical. If someone makes a totally unqualified statement like “dynamic typing is better” I tune them out.
Why is it so hard to have static and dynamic in the same language? One would be able to choose what when to use static or dynamic typing.
Danny: You can have both. C# is statically typed in general, but in version 4 it added an optional
dynamic
type. And there have been moves in the opposite direction, adding optional typing to dynamic languages.It goes back to how you use the language. In practice, dynamic language code isn’t that dynamic; programmers don’t take advantage of the dynamic features all that often. (This helps optimizers make intelligent guesses about how a variable will be used, even though there’s no guarantee.) And statically typed languages aren’t purely static in practice. For example, you can use a
void*
in C to get away with murder.It seems that relative advantage of static over dynamic is a function of how much your design changes. There seems to be an analogous issue in database design — http://lemire.me/blog/archives/2010/11/29/why-do-we-need-database-joins/
This is pretty much the definition of weak typing: If there is a way to access data in a manner contrary to its type’s definition (for example, to access the bits comprising a floating-point number as if it were an integer), the type system has a weakness. A type system with ‘enough’ weaknesses is generally referred to as weak.
This is orthogonal to static and dynamic, although I can’t think of any modern languages with weak dynamic typing.
The practical difference between strong and weak typing in a language with dynamic typing is the difference between a core dump (or other hard crash) and an exception being raised.
(Why, yes, it does annoy me when people conflate ‘weak’ and ‘dynamic’ typing! How did you ever guess!)
Chris: I can subvert the world’s strongest type system. I’ll just make every method receive a string and return a string, all strongly typed. Inside each method I unpack each string to be its actual data type.
Here’s another subversive strategy. Every method takes a string, which is the name of a DLL. Or if you’d like, a strongly typed object representing a DLL. The method then calls “Go” on the DLL. Or if you prefer, every method takes a the URL of a web service and invokes it. In either case, the code can do anything.
Chris: how would you specify which operations on x are contrary to x’s type definition?
Suppose x represents probability distribution. It’s too much work to define “ProbabilityDistribution” class and I store x in array of numbers. Then I multiply it by -1. It’s really the same kind of type error as multiplying bits of floating point numbers as if they were integers, and you need a mind-reading type system to prevent it
@John: You can implement a type-free language with any language, like you can implement a strongly-typed language with any language or, more to the point, you can impose disciplines on your code that give you the effect of having strong typing in the language assuming you always follow them.
My rebuttal to your point is that every language has a ‘style’, which you can only subvert by greenspunning. The first technique you describe is pure greenspunning; the second you describe is a hole in the type system that, to my (limited) knowledge, no modern language has patched.
@Yaroslav Bulatov: A good question, which goes to the whole notion of how to use a type system correctly and how good any type system can be if it doesn’t allow programmer-created types.
My point with what I said amounted to a hole in the type system being a way to ‘go back on your word’ with regard to what a piece of data was defined as. If you have no way to apply types at all, as in assembly language or Forth, this doesn’t apply: A nonexistent type system cannot have a hole.
Utterly inexpressive type systems, that don’t allow any programmer-created types, have holes in that they cannot enforce any new semantic rules you may wish to create, like ‘you can’t cross a vector with a scalar’. They may or may not not have holes like C has holes, however, in that the abstractions the language provides natively could well be absolute and impossible to subvert. An example of this would be a trivial Lisp dialect, say, that does not allow the creation of new types but also strictly checks every operation and has no concept of typecasting. That’s strong typing as far as the type system goes, but it certainly is a trivial kind of strength. However, as you said, if we consider this to be weak typing then there is no way for any language to be absolutely guaranteed to be strongly typed all the time for every possible program.
Chris: you say “subvert the type system” as if it’s a bad thing. Imagine if you couldn’t use plain float[] for probability distributions, or float[][] for covariance matrices. Even if you had the time to explicitly specify allowable operations for your “covariance matrix” data type, some of the type checks may not be practical to run. In the case of covariance matrices, your type checks may take O(N^3) time to run. I can think of some types where type checks are exponential time unless P=NP