5

For most of my career, I've been working with strong static typed languaged such as Java. For this reason, probably I've mixed up these two typing dimension (strongness and staticness). I came upon this link, which says that they are actually orthogonal dimension. I read it, but still can't understand this distinction. 'weak static' sounds oxymoron to me, because static sounds like they will check stuff at compile time, while weak is the opposite.

The page uses Pascal and C as examples of weak static, and CommonLisp and Python as examples of strong dynamic, but unfortunately I don't know enough of these language to help.

What does weak static typing/strong dynamic typing mean? How can a language like C and Python be like Java in one aspect, but like Perl in others?

  • 1
    Related: The Definition of “Strong Type Systems” – user40980 Sep 19 '15 at 22:52
  • 2
    It's a shame that this question is unanswerable, but this is what happens when people misuse words so much for so long that the words lose all semblance of meaning. – Ixrec Sep 20 '15 at 19:12
11

The terms strongly typed and weakly typed dont have a agreed-upon definition. Therefore, unless you define what you mean by "strongly typed" and "weakly typed", it is impossible to answer your question.

It makes a "great" argument in a flamewar, because whenever someone is proven wrong, they can just redefine the terms to mean whatever they want them to mean. Other than that, the terms serve no real purpose.

It is best to just not use the terms, or, if you use them, rigorously define them first. If you see someone else use them, ask them to define the terms.

This is what Benjamin C. Pierce, author of Types and Programming Languages and Advanced Types and Programming Languages has to say:

I spent a few weeks... trying to sort out the terminology of "strongly typed," "statically typed," "safe," etc., and found it amazingly difficult.... The usage of these terms is so various as to render them almost useless.

Luca Cardelli, in his Typeful Programming article, defines it as the absence of unchecked run-time type errors. Tony Hoare calls that exact same property "security". Other papers call it "type safety" or simply "safety".

Mark-Jason Dominus wrote a classic rant about this a couple of years ago on the comp.lang.perl.moderated newsgroup, in a discussion about whether or not Perl was strongly typed. In this rant he states that within just a few hours of research, he was able to find 8 different, sometimes contradictory definitions, mostly from respected sources like college textbooks or peer-reviewed papers. In particular, those texts contained examples that were meant to help the students distinguish between strongly and weakly typed languages, and according to those examples, C is strongly typed, C is weakly typed, C++ is strongly typed, C++ is weakly typed, Lisp is strongly typed, Lisp is weakly typed, Perl is strongly typed, Perl is weakly typed. (Does that clear up any confusion?)

Everybody has their own definition. Some that I have seen are:

  • strongly typed = statically typed
  • strongly typed = explicitly typed
  • strongly typed = nominally typed
  • strongly typed = typed
  • strongly typed = has no implicit typecasts, only explicit
  • strongly typed = has no typecasts at all
  • strongly typed = what I understand / weakly typed = what I don't understand
  • strongly typed = C++ / weakly typed = everything else
  • strongly typed = Java / weakly typed = everything else
  • strongly typed = .NET / weakly typed = everything else
  • strongly typed = my programming language / weakly typed = your programming language

In Type Theory, there exists the notion of one type system being stronger than another. In particular, if there exists an expression e1 such that it is accepted by a type system T1, but rejected by a type system T2, then T2 is said to be stronger than T1. There are two important things to note here:

  1. this a comparative, not an absolute: there is no strong or weak, only stronger and weaker
  2. there is no value implied by the term; stronger does not mean better (in fact, the "strongest" type system is then the one which simply rejects all programs, which is clearly not useful)

The only definition that I have seen consistently applied is:

  • strongly typed: my programming language
  • weakly typed: your programming language
  • 5
    In other words, they don't mean anything. – Robert Harvey Sep 19 '15 at 16:38
3

Introduction

To really answer that question you have to first understand the purpose of why we even use a type system. And you just have to understand static and dynamic on its own. The same goes for strong and weak. If you understand the definitions separated you can just put those together in every combination. And you will also see the problems that raises if you understand all of those definitions.

Type Systems

So at first let's look at what a "type system" really means. Back at the beginning of computing all we really did was directly coding to the computer. Meaning directly writing machine code. And if you do that you face one thing that there doesn't exists any types at all. The only things that a computer really sees are zeros and ones. That is basically a problem because it means there are a lot of possible errors. For example take the character a if you encode that character in ASCII encoding it will be represented as the number 97. That number represented as bits looks like this 0110 0001. But here starts the problem. What happens if you also want to save the number 97 somewhere, then you also end with the exact same bit representation. What is if you want to compare the character a with 97? The problem that you face is that the computer only sees zeros and ones. The information about the type that you as a human had a is a character and 97 is a number is completely lost. If you would start to compare those two things, your computer would just return a is equal. Because for the computer he only sees the bits and a and 97 has the same memory representation.

That in fact is a great problem and what you have to do is basically somehow in your application keep track on your own whether something was a number or a character and make sure that you cannot compare those things, or if you compare those things it will result in a not equal. But instead of keeping track on all that stuff on your own, we invented the type system. Instead of dealing with all that stuff for yourself, now the language provides a type system. On top of just saving just zero's and one's it will also keep track of the information about the type. If you try to compare a with 97 it will additional look at the types. It will identify that one thing was a character and the other thing was a number. So even if both things have the same bit representation in memory it now can give you the result not equal. So the whole purpose of a type system is to help humans in programming to spot errors as early as possible.

That was also the first meaning we had of weak vs. strong typing. It basically just meant if you have a type system that is able to identify different types. The term weak typing just meant that it doesn't knew anything about types, so for example comparing a number and a character that have the same bit representation would return equal. And strong typing meant you had a type system, and the language is able to differentiate different types.

But there is now a different problem. If we would still use that definition of weak and strong typing those words become meaningless. Because today every language has a type system and would be strong typed. So the definition of what is strong typed and weak typed changed over time. That is also another thing i will later explain further. That differentiate between weak and strong doesn't really makes sense at all. But let's forget about that for a minute. Let's look at static and dynamic for a moment.

If your language is able to differentiate two types that also raises other questions. For example comparing a character with a number will always result in not equal. You don't even have to look at the real value that is saved in memory. Just by looking at the types itself you already now it will always be not equal. But if it will always be not equal why do you compare those two things in the first place? The answer to that is that comparing those two things is probably an error in your programming logic.

So the questions that raises are:

  • Should comparing two different types result in an error, or should it always return just a not equal?
  • If comparing two types result in an error. Should that error be a compile-time error or a runtime error?

Those are interesting questions on its own. But the last question has a important thing in it. We made a distinction between if something should happen at compile-time or runtime. And that leads to static typing and dynamic typing. When we assume that the types are known at compile-time we name it static typing, if the types are only known at runtime we name it dynamic typing.

And the first question itself even raises another question. If you for example decide that comparing two different types should not raise an error, then comparing those will will always return not equal. But that doesn't make much sense. So why not give it more sense? So the next question that raises is.

  • When you compare two different types. Should there be a type conversion from one type to another?

So what are the answers to all those questions? The answer is that there doesn't exists really an answer. People that invented languages all gave different answers to those questions and created language with different mindsets. And there is even another thing. Based on which types we are talking you can come to different results! But because of those questions and that everybody gave other answers what we see as strong typing and weak typing changed. It's not anymore just about having a type system or not. Strong and weak is about how it behave.

Example 1

Nowadays people think of strong typing when a language throws errors if you do an operation on two different types or in general do an operation on a type that don't support this operation. But if a language does a type conversion instead of throwing an error we see it as weak typing. Static typing or dynamic typing in general just means if the types are already known at compile-time (static) or runtime (dynamic). It doesn't even assume some behaviour. That all now sounds like a reasonable explanation, so why did I stated above that differentiate between strong and weak makes still no sense at all? It is best explained in an example. So lets say we have two different types a string "10" and an integer 10. Let's just explain what the result of the four possible combination would be

Operation: "10.0" == 10
Results:

  • dynamic and weak -> true
  • dynamic and strong -> runtime error
  • static and weak -> true
  • static and strong -> compile-time error

Now let's quickly explain why we have those four result.

1. Dynamic and weak
The information that we have a string and an int is only known at runtime. When we compare the results at runtime, we do convert the string to an int, after converting, it results in true.

This Raises another question:
Why converting string to int? Why not converting the int to a string? If you convert the string to an int like above you get true. But if you do the conversion from int to string you will probably get false. Which one is correct? Answer none. It also doesn't matter if it returns true or false it will still be dynamic and weak typed. In fact you can't really say what it returns at all! You have to read the language design to understand whether it will return true or false

2. Dynamic and strong
The information that we have a string and an int is only known at runtime. But because those are different types, those operation is not allowed. This code will throw an error at runtime.

3. Static and weak
The information that we have a string and an int is already known at runtime. But because we are weakly typed and allow type conversion (only possible at runtime) we basically don't do anything with that information. At runtime we do a type conversion. In fact the behaviour is the same as dynamic and weak and it also raises the same question!

4. Static and strong
The information that we have a string and an int is already known at compile-time, those operation is not allowed, the compiler will create a compile-time error and this code will not even compile.

Example 2

At that point you might think. Okay, but this is still reasonable! Based on those results i still can categorize languages as strong or weak and static or dynamic. So why does strong and weak makes no sense at all, like i stated before? Well, it's not that those definition makes no sense. It doesn't make sense to label languages as strong or weak. And the next example will show what i mean. We now compare int and float.

Operation: 10 = 10.0
Results:

  • dynamic and weak -> true
  • dynamic and strong -> runtime error
  • static and weak -> true
  • static and strong -> compile-time error

In fact, nothing changes in this example! The results, the questions and the explanations are the same as with the example above! And sure, it has to be the same! Because it doesn't matter which type we use. If we use string and int or float all of those types are different and should end in the above results. But if you look at Java, C# and so on. What i have shown here is not what is happening in those languages!

The Real World

Most languages do something different based on the types! Lets for example look at C#

string x = "10.0";
int    y = 10;
bool ret = x == y;

The above code will produce the compile-time error: Operator '==' cannot be applied to operands of type 'string' and 'int'

So in that case the language behaves like static and strong. But if we write.

float x = 10.0f;
int   y = 10;
bool ret = x == y;

Suddenly there is no error anymore! C# ignores the different types at compile-time and just did a type conversion at runtime! In that case it will convert the int to float, and then do a comparison at runtime. In that case C# behaves like a static and weak language! If you are used to those things it sounds reasonable to you, but it isn't really. The language designer just answers all the question above different and not in a general sense. They even do it based on the type! For some reason they thought that comparing some types sometimes does a type conversation at runtime, and sometimes produces an error at compile-time, completely depending on the type you use in your code! And to just look at another language to see that there exists language that have another behaviour. If you do the last thing in F#, F# also behaves in this case like "static and strong"

let x = 10.0
let y = 10
printfn "%A" (x = y)

This F# code will highlight the y in the comparison and will produce the compile-time error: This expression was expected to have type float but here has type int

So it basically says that it cannot do the equal operation because there is a type mismatch. But now everything starts to crumble! Usually C# and F# are both defined as static and strong typed languages. But how can both be strong if F# throw an error by comparing int and float, but C# don't do that?

The Problem in definitions

And that is the problem. Strong and weak have a meaning, but often it doesn't make sense to label a language as strong typed because not everything is probably really strong typed. If you think in absolute terms then C# would be a static and weakly typed language. But sure a lot of people will complain at that, because most of the time C# behaves like static and strong. But those problems are really the core problem on why saying a language is strong and weak in absolute terms makes no sense.

Those are also the reason why we usually say (as an example) F# is stronger typed than C#. But that whole sentence doesn't makes really sense. The definition of strong and weak are absolute. The sentence that something is more stronger don't make any sense at all. Either it is strong or weak. But because humans still wants to put everything into categories you still end up with definitions that often have no meaning at all. And let's look for example at Python. If you write the following code in Python

10 == 10.0

You will get a runtime-error! So even Python in that case behaves like a strong typed language. But because the types are only known at runtime. Python can only throw an error at runtime and doesn't can point that error out already at compile-time.

So what you see here is that strong and dynamic is not really a problem at all. Strong typing is just how an operation behaves on different types. And sure a dynamic typed language also can throw errors on different types. So both are strong. But throwing the error at compile-time makes something static and doing it at runtime (through an exception) makes it dynamic.

But overall it is hard to really say a language is strong or weakly typed because most languages don't implement the absolute terms. Like i showed by comparing an int with a float" C# behaves like a weakly typed system. But Python or F# on the other hand behaves like a strong typed system.

Usually what most people do is: "If most of the things behaves strong, a language is considered strong". But how do you measure those things? And do you measure it and if you come to the conclusion that 51% of the operations are strong, so the language is strong? What happens if you build new features in the language and now you end up with 49% of your statements are only strong. Does a language change from strong to weak? Can it go back to strong if most operations are strong again? That is the point why labelling languages as "strong" and "weak" makes no sense at all. If you are absolute you must ensure that every operation in the language is "strong". But that would label most languages including C++, C#, Java and so on as a "weakly typed" language.

On top of that just one note because you said it in your question. The general consensus nowadays is that C is a weakly typed language. Not a strong typed one.

Conclusion

You hopefully now understand how a language like Python is for example said to be strong and dynamic. Both things can work without problems together, because both things are not really related. And it probably even helps you to understand why those statements also makes no sense at all. Something that looks strong to you, can look weak to others.

  • I disagree on "strongness" being an absolute. I believe it is a gradient and that some languages being weaker or stronger than others is natural thing. – Euphoric Sep 19 '15 at 10:41
  • @Euphoric You basically agree with me. If the typing is gradiant you cannot label a language as "strong" or "weak" because those terms are absolute. If it is gradient at which point will it turn into strong and at which point will it turn into weak? And like i already mentioned. How do you measure it? If you think typing is gradiant (what i even showed) then using absolute terms like strong and weak makes no sense. We basically had to invent a strongness scale and saying F# has a strongness of 90 and C# of just 70. If you have that, you can sure say that F# is stronger than C#. – David Raab Sep 19 '15 at 10:52
0

Static type checking occurs at compile time. Dynamic checking occurs at runtime.

Strongly or weakly typed refers to how strict the type system is. Some type systems allow "loopholes" in the language where you can subvert the type checking. ADA is one such language; the Ariane 5 accident was the unfortunate result of such a type subversion in that language.

Some languages allow type checking at both compile time and runtime: C# is such a language (see the dynamic keyword, which defers type checking to runtime). Haskell and OCaml are considered some of the most strongly-typed languages, while C and Javascript are weakly-typed. C is staticly-typed; Javascript has dynamic typing.

  • To be precise, strong and weak typing does not have an universally accepted definition but is rather used informally as a value judgement. Therefore, these terms should be avoided unless they are accompanied with a precise definition. E.g. I assume weak typing to refer to reinterpreting casts, most people thing of implicit type conversions. Please also note that any OOP language necessarily contains a dynamic typing aspect since the target of a virtual method dispatch is generally unknown until runtime. – amon Sep 19 '15 at 5:14
  • Are you really saying that Ada is not strongly typed? – coredump Sep 19 '15 at 5:52
  • 1
    @coredump: That's just what I am trying to say in my answer. "Strong" and "weak" typing don't have any agreed upon definition. Since they don't have any agreed upon definition, there are dozens of different, incompatible, contradictory definitions floating around already, and in every flamewar and/or discussion at least one person invents another one. In this case, Robert chose the definition "is free of loopholes". And according to that definition, Ada is weakly typed. And so is Haskell (because of unsafePerformIO). Remember: a scientific term means what its definition says it means. … – Jörg W Mittag Sep 19 '15 at 13:38
  • … Nothing more, nothing less. In particular, it does not necessary mean what you think it should mean. There's a famous case of this in mathematics: a mathematician had essentially invented non-Euclidic geometry, but because the notion of "point" arising from his axioms and theorems didn't agree with his preconceived notion of what a "point" should be, he assumed that he had proven that Euclid's 5th axiom was correct. When in fact, he had just invented a new, different kind of geometry with a different 5th axiom. He could be remembered as the inventor of non-Euclidic geometry, but now … – Jörg W Mittag Sep 19 '15 at 13:42
  • … he is remembered as the guy who didn't understand the difference between a definition and an intuition. – Jörg W Mittag Sep 19 '15 at 13:42
0

Static and dynamic is the easy axis to explain, because it refers to when your types are checked: at compile time or runtime respectively.

In the most simplistic terms, on the weak-strong axis, the stronger your types, the more likely the programmer is to get a type error instead of some other kind of error when he screws up. You try to compare a number with a boolean in C, no problem. Try it in python, you'll get a type error at runtime. That's why python is said to be more strongly typed.

However, that's not the entire picture, because many of the more advanced type system features are designed to help you avoid type errors. As your types get stronger you get more and more frequent type errors, so people invented ways to help you take them away again, such as generics, inference, and implicit conversion. This makes the type system more expressive, but it's a matter of intense debate whether those features strengthens or weakens the type system.

  • You try to insert a number and a boolean in a Python array, no problem. Try it in C, you'll get a type error at compile-time. That's why C is said to be more strongly typed. – David Raab Mar 28 '16 at 1:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.