There’s a scene in just about any Victorian period movie where a gentleman take off his glove and slaps another gentleman across the face in it. Or, if they’re going for historical accuracy, perhaps just throws it on the ground at his feet. A duel follows shortly after.
Where was I? Right, Unicorns. They don’t exist. Neither does strong typing. Or weak typing. More accurately, there does not currently exist a useful definition of the two terms that is widely accepted, and which can be used as the basis for a rational conversation about their relative merits. This is why the terms are only good for starting fights.
Don’t believe me? Let’s take a look at the definitions provided by that ultimate source of truth, Wikipedia.
In computer science and computer programming, a type system is said to feature strong typing when it specifies one or more restrictions on how operations involving values of different data types can be intermixed. The opposite of strong typing is weak typing.
Great, so it’s strongly typed if it “specifies one or more restrictions on how operations involving values of different types can be intermixed”. And its opposite is weak typing. Let’s see what Wikipedia has to say about that.
In computer science, weak typing (a.k.a. loose typing) is a property attributed to the type systems of some programming languages. It is the opposite of strong typing, and consequently the term weak typing has a number of different meanings, just as “strong typing” does.
Well okay then, so we’ve confirmed that weak typing is indeed the opposite of strong typing. That should clear things up. Let’s talk about something else.
1 2 3 4 5 6
1 2 3 4 5 6 7 8
1 2 3 4 5 6
They all appear to be adding an integer and a decimal number together, but all is not as it seems.
In most languages, an integer and a floating point number are very different things, at least to the compiler. Signed integers are generally represented as two’s complement while decimals are represented with the IEEE’s floating point standard.
This means that to a computer, 1 and 1.0 may not be the same thing. One may be two’s complement, and the other floating point, so 1 and 1.0 may actually be represented by a different sequence of bytes! You can’t directly add them together.
What Ruby and Scala both do is implicitly convert the two’s complement integer into a floating point number before doing the addition. This is most apparently in the Scala case, where Scala tells us that the result of adding together an Int and a Double is, indeed, a Double.
Implicit conversions are at the heart of most discussions on strong and weak typing, as is hinted at by Wikipedia definition of strong typing - “…specifies one or more restrictions on how operations involving values of different data types can be intermixed”. The intuition here is that if you can’t reasonably perform an operation on values of two different types, possibly by implicitly converting one type to another, than the language should disallow it.
The problem with that definition is that it fits almost every language, for some definition of reasonable. Without implicit conversions, we’d lose a whole ton of convenience, like adding an integer and double together, or concatenating a number on to a string, or assigning an unboxed int to an Integer in Java. However, the more aggressive a language gets with its implicit conversions, the more dangerous they can get. Java is rather conservative here which is why its often called strongly typed, though the conversion from unboxed to boxed numbers, for instance, can have very surprising effects on a program’s memory usage and runtime.
Anyhow, that’s why most discussions about strong and weak typing just degenerate into anarchy. The only workable definition is that a language is weakly typed is that it does implicit conversions you consider bizzare, and it’s strongly typed if it doesn’t. Computer scientists don’t seem to use the terms anymore, they prefer to talk about the type safety of a given type system.
As a side note, Scala give programmers the power to define their own implicit conversions. Here, for instance, is an implicit conversion that will convert from a Scala function to a Java Runnable.
1 2 3
With that implicit defined somewhere in a project, the Scala compiler will convert Scala functions to Runnables when it has a Function and needs a Runnable. It may seem that exposing this sort of power to application developers is dangerous, but rest assured, it was added to the language only after it was discovered that shipping butcher knives without handles to the entire Scala userbase would be prohibitively expensive.