Reading through the articles on programming languages, you are bound to stumble upon statements similar to the following:
(Aside: Wikipedia pages of individual languages themselves have a bullet titled “Typing Discipline” in the sidebox).
Depending upon your programming background and experience, the above statements might either look deceptively simple to read or seem downright counter-intuitive, yet they are the source of some very famous warts in the respective languages.
A good understanding of the fundamentals behind such statements can help programmers develop more reasonable expectations from the code they write.
We begin by defining 4 terms central to the discussion, namely:
The terms grouped are semantically antonyms to each other.
Each group defines important characteristics of a programming language independent of the other group.
Whether a language is statically typed or dynamically typed depends on how the compiler/interpreter handles variables and at what point during the execution of the program.
In a statically typed language, the variable itself has a type; if you have a variable that’s an integer, you won’t be able to assign any other type of value to it later. Some statically typed languages require you to write out the types of all your variables, while others will deduce many of them for you automatically.
Moreover, the compiler can tell which the type of a variable, without executing the program.
In a dynamically typed language, a variable is simply a value bound to a name; the value(or object) has a type – like “integer” or “string” or “list” – but the variable itself doesn’t. We can have a variable which, right now, holds a number, and later assign a string to it.
The programmer is free to bind names to different objects with a different type. So long as you only perform operations valid for the type the interpreter doesn’t care what type they are.
At present, almost all programming languages support only static or dynamic typing, or they favor one of them.
Dynamic and static typing have different costs and benefits. Picking the best one for a particular task is not always easy.
Static typing has the following main benefits:
Dynamic typing has a different, complementary set of benefits:
The benefits of static typing are more pronounced for large and complex programs. It offers little benefit over dynamic typing when writing short scripts and prototypes, for example. In these cases, it mainly slows down the programmer and dynamic typing is preferable.
>>> age = 21
>>> age = '21'
Conclusion: The type of name age
is the type of the object it refers to at that particular instant. Moreover, no further restriction is laid on it with regards to what values it can/cannot hold in the future.
age := 21
age = "21"
Conclusion: A compile-time assignment error is raised. Once a type is associated with a variable, the variable cannot hold a value of other data types.
age = 21
age = "21"
Conclusion: Same as Python
The distinction between such typing comes to the fore when we write programming statements which involve operating values of different types.
To resolve the error raised in a strongly typed language, the programmer needs to explicitly convert the type of values to the desired type.
The terms “strong” and “weak” are themselves relative by nature. Thus, a person calls some programming language “X” as strongly (or weakly) typed is subjective. From the First Principles perspective, what the person wants to claim is that language “X” enforces type checks before performing any operations. Every developer will have a different measure of how rigorous these checks are.
Rule of Thumb: the more type coercions (implicit conversions) for built-in operators the language offers, the weaker the typing. (This could also be viewed as more built-in overloading of built-in operators.)
i.e a strongly typed language is restrictive of type intermingling.
Let us understand this distinction with 2 operations which every programmer must have comes across:
Strong Typing:
Weak Typing :
Hence weakly typed languages helps in faster application development and more expressiveness of programming logic (like ad hoc-polymorphism, mix-ins) than strongly typed.
>>> a, b = 10, 'K'
>>> a + b # Binary operation on different types
...
TypeError: unsupported operand type(s) for +: 'int' and 'str'
>>> a + ord(b) # Explicit type conversion of string to integer
85
>>> str(a) + b # Explicit type conversion of integer to string
'10K'
>>> a, b = 1, 2.5
>>> a + b # No error
3.5
Conclusion: Raises errors when sense cannot be made. Also, the interpreter is not restrictive enough to spoil the fun in programming.
func AddNumStr() {
a, b := 10, "K"
fmt.Println(a + b)
}
func AddNumFloat() {
a, b := 1, 2.5
fmt.Println(a + b)
}
Conclusion: In both the cases, an “invalid operation” compile-time error is raised.
> a = 10
> b = "K"
> a + b
'10K'
> a = 1
> b = 2.5
> a + b
3.5
Conclusion:
The compiler implicitly converts the type of values to make sense of the operation rather than raising errors.
I hope that after reading this article, you can justify the statements regarding the type systems used in different languages. In this post, I explored these principles across Go, JavaScript & Python just to cover a variety of examples.
Thank you!
#python #javascript #go