DEV Community πŸ‘©β€πŸ’»πŸ‘¨β€πŸ’»

Cover image for Static and Dynamic typing? Strong and weak typing?
Leonardo Guedez
Leonardo Guedez

Posted on

Static and Dynamic typing? Strong and weak typing?

Table of contents

Intro

When talking about typing in programming languages, we tend to confuse the meaning of some terms. We all have some notions of static vs dynamic typing, and may even give some examples of strong vs weak typing based on languages we know. But can we really explain these concepts to someone who is hearing them for the first time? Could we write a blog post about them?

In this post I'll try to explain these concepts in simple terms so you can finally have that "aha!" moment where you can talk about them with more confidence.

Static vs Dynamic

To talk about static vs dynamic typing and strong vs weak typing is to talk about opposite poles of different axis. Let's go with static typing first:

Static typing

In static typing, the type is bound to the variable. Types are checked at compile time.

That means that in a statically typed language, once the variable has been declared with a type, you can't change that type later; you can of course assign it new values, but they must be of the same types. Remember: the type is bound to the variable, not the values.

Let's see some code snippets in Java β˜• :

String s = β€œhello”;
System.out.Println(s)  // "hello"

s = β€œgood”;
System.out.Println(s)  // "good"

s = "world";
System.out.Println(s)  // "world"
Enter fullscreen mode Exit fullscreen mode

This code is completely valid; s is of String type, and so are the values given to it.

But if we tried to do this:

String s = β€œhello”;
System.out.Println(s)  // "hello"

s = 5;
System.out.Println(s)
Enter fullscreen mode Exit fullscreen mode

The program wouldn't compile and we'd see an incompatible types error: we can't assign an int to a variable of type String.

The key take away of all this is that in static typing, the type associated to the declaration of a variable is permanently bound to it and you can't change it with later assignments. You can assign new values of the same type though.

Dynamic typing

On the other hand:

On dynamic typing, the type is bound to the value. The checks are made at runtime.

As the type of the variable is bound to the values, it can change along with the type of the values assigned:

The following snippet in Python 🐍 :

x = 1
print(type(x))  # <class 'int'>

x = β€œhello”
print(type(x))  # <class 'str'>

x = 3.14
print(type(x))  # <class 'float'>
Enter fullscreen mode Exit fullscreen mode

Is perfectly valid and run without issues, because the type of x depends just on the values assigned (int, str and float, respectively).

But if we now try it in Golang, a statically typed language, it would not even compile:

var x int = 5
fmt.Println(x)

x = β€œhello”
fmt.Println(x)
Enter fullscreen mode Exit fullscreen mode

because we already told the compiler that x is of type int.

But what about type inference?

Yes, in Golang (and many other languages) we've got type inference, but that doesn't mean that the language is not statically typed. In short, type inference means that the compiler/interpreter can infer the type of the variable without you explicitly pointing it out.

Let's change the Golang snippet:

var x int = 2  // long declaration, explicitly indicate the type

x := 5  // short declaration, uses type inference
fmt.Println(x)

x = β€œhello”
fmt.Println(x)
Enter fullscreen mode Exit fullscreen mode

This is still invalid Go code; not because you have type inference means that the language is dynamically typed. Type inference serves as a good convenience for the programmer, but it's not exclusive to dynamically typed languages.

Strong vs weak typing

The problem with the terms strong and weak typing is that there simply isn't a single canonical definition; we all can sort of agree and say more or less the same things, but there is not a formal definition to adhere to.

In any case, strong typing usually means that the compiler forces a sort of "type discipline" at compile time; there should be more strict typing rules at said time; generally, this has todo with variable assignments, function arguments and return values.

On the other hand, weak typing supposedly has more lax type verification rules.

Common uses

Generally, dynamically typed languages tend to be associated with interpreted languages like Python, Ruby, Perl or Javascript, while statically typed languages tend to be compiled, like Golang, Java* or C.

However, this doesn't imply that the typing discipline of the language is bound to the way it's translated: a language can perfectly be statically typed and interpreted at the same time, as can be dynamically typed and compiled.

Also, there is also room for middle ground between static/dynamic and strong/weak:

  • C, despite being statically typed, is also considered to be weakly typed, because with casts you can change a value of one type to be of other type, mainly when using pointers. This has pros and cons, but C assumes that the programmer knows what the heck he's doing (haha!) and gives him the liberty to do so.

  • Python is dynamically typed, but it's also considered strongly typed.

*Java is actually a particular case, because it has an hybrid translation model, both compiled and interpreted at the same time.

Pros and cons?

Usually, dynamically typed interpreted languages are useful for prototyping and iterating quickly over ideas, testing them without too much hassle. It's common to use Python or Ruby for this, checking if the algorithm works as expected; their dynamic nature allow us to concentrate more on the idea rather than on the implementation details of the language, like exactly knowing the types of the variables, eliminating boilerplate code.

However, these kind of interpreted languages tend be slower than compiled languages, in terms of run time efficiency. This is something well known, and although this efficiency gap has been reducing, it's still a good thing to have in mind.

Finally, dynamically typed languages tend to defer type errors to runtime, so a rigorous testing strategy is vital to catch all code flows at development time.

On the other side, statically typed languages tend to catch and show type errors at compile time, like passing a string to a function that expects an integer, which really help us to be more confident of the code that we deploy.

TLDR

  • Static/Dynamic are poles of the same axis, and it's where we have more consensus on definitions. The theory is more clear, developed and explicit.

  • On static typing, the type is bound to the variable/object.

  • On dynamic typing, the type is bound to the value assigned to the variable object at a given moment, and can change as the type of the value assigned changes.

  • Strong/Weak are poles of another axis, and although there some general ideas about each one, the differences and characteristics are not so clearly defined.

And that's it, thanks for reading! Hope you liked this post :) If you want you can subscribe so you know when I publish more content :D

Useful readings

Top comments (0)

Dream Big


Use any Linode offering to create something unique or silly in the DEV x Linode Hackathon 2022 and win the Wacky Wildcard category.

β†’ Join the Hackathon <-