Programming Types
The Birth of Types
If you’ve ever written code in a language that requires specifying types when declaring variables, you almost certainly felt a bit of frustration along with it. Some languages perform calculations without needing to explicitly define types, and writing what seems like messy and meaningless code feels like a waste of time and energy. Imagine programming environments before the concept of types existed.
The data computers understand consists of numbers, and from a human perspective, it’s impossible to tell if those numbers represent integers, strings, etc., just by looking at them. Of course, it would be fine if the person who wrote the code remembers everything, but as programs become more sophisticated and go through multiple hands, it becomes easy to get confused about what was what, leading to bugs. Squaring a string might yield some number, but that’s a minor issue compared to bugs. For example, if hundreds or thousands of lines of code contain an integer that has been multiplied by a pointer but still looks like an integer, how on earth are you going to catch that bug? The program might look fine, but the results are a mess.
The immediate sensible response seems to be ‘writing detailed comments to make it easier to understand.’ For instance, noting down that A is an integer, B is a string, and so on. The next question is ‘are these comments reliable?’ It’s good to annotate every variable with comments to reduce bugs and increase productivity. If there’s diligence to correct those comments when the purpose of a variable changes, then it’s fortunate. However, comments are also made by humans, and due to mistakes, even comments can be wrong, so it’s better to have syntax that can precisely specify what exactly a variable is.
This idea might feel familiar. Yes, this is precisely type declaration.
Thus, types initially served a purpose similar to comments specifying what variables were, but their role became more prominent, and research on them continued.
Strong and Weak Typing
Weak typing is a term contrasted with strong typing and hasn’t changed much from the previously mentioned concept of types. Languages with weak typing run code as long as there are no issues with type checking, even if it’s against the programmer’s intention. This ’trust in the programmer’ attitude touts faster speeds but led to the conception of strong typing to catch bugs in advance and increase productivity.
Strongly typed languages ensure that the program runs correctly as long as there’s no issue with type checking. Complaining about bugs all the time isn’t an option as stricter checks prevent dangerous and significant bugs from returning later on. Strictness in type checking is a constraint, but in programming, constraints often mean ‘convenience’ rather than ’limitation.’ If the type system is strong, it’s not ‘annoying because you have to specify all types’ but ‘allows detailed adjustments according to the programmer’s needs.’
While weak typing has its pros and cons, it wasn’t exactly intended, and it’s reasonable to see it as simply naming the primitive concept of types to explain why strong typing is called strong typing.
Static and Dynamic Types
Static languages perform type checking at compile-time, whereas dynamic languages do so at runtime, i.e., when the code is actually running. In simpler terms, static languages are compiled languages with fixed data types, while dynamic types belong to interpreted languages with data types that can change on the fly. Obviously, compiled languages need to be recompiled entirely even for minor changes, so interpreted languages have higher productivity, but once the compilation is done, compiled languages have a significant advantage in speed.