I heard that semantics and type systems are very important for all programmers! But I why are they so important? I don't understand. Maybe they are imortant only for theoreticians and compiler developers?

In my practice I never think about semantics and type theory. As for me it is enough to know that the semantics defines the meaning of syntax. When I write + I just know that it is the addition operation. And it is enough for me.

Then, I want to describe my thoughts about type systems. Also, when I write int i;, I know that int is an integer and it is enough for me.

Another case - it is important to know what the difference beetwen static and dynamic, weak and strong type systems.

Tell me please, are there any practical benefits from the knowledge of semantics and type systems?

  • For semantics IMHO they are more relevant on a level of language design and implementation (not that other programmers would not profit from knowing about it since it will help understand what actually happens and how to avoid certain pitfalls in some languages). For type systems this is quite different since you will make decisions based on how a language handles types (one of the most important if a language with a certain type system can even be used for some projects). It will have a very strong effect on how your code looks and how complex it may become for certain tasks. Commented Jan 25, 2016 at 10:11
  • One example of such a pitfall may be be PHP's left associative handling of the ternary operator: stackoverflow.com/questions/20559150/… Commented Jan 25, 2016 at 10:23
  • 1
    @thorstenmüller I'd consider associativity a syntactic issue. Commented Jan 25, 2016 at 10:47
  • 1
    please don't cross-post: stackoverflow.com/questions/34989195/…
    – gnat
    Commented Jan 25, 2016 at 13:36
  • 2
    Semantics is the question of what an operation does. The semantics of the + operator is addition. So semantics is critically important - if you don't understand the semantics of a language, nothing at all makes sense.
    – JacquesB
    Commented Jan 30, 2016 at 12:25

2 Answers 2


Sublte semantic differences

Consider this simple program:

i = 1000'000'000
j = i * i

This operation can behave very differently depending on the semantics of integers in your language:

  1. Some languages will seamlessly switch to big integers producing the correct result (1000'000'000'000'000'000), but degrading performance (e.g. python)
  2. Some languages will seamlessly switch to floats, producing an approximate result (e.g. javascript and php)
  3. Some languages will raise an error because the result doesn't fit a 32 bit integer (e.g. C# with checked arithmetic enabled)
  4. Some languages will wrap around (e.g. C# with checked arithmetic disabled, returns -1486618624). The precise wrap around behaviour can differ depending on the size of the integer type and the representation of the sign (C# uses two's complement)
  5. Some languages will invoke undefined behavior (e.g. C and C++)
  6. Some languages will consider the literal signed, others as unsigned

Pretty big differences for something as simple as multiplying two integers.

Or consider the case where you write 1 + "1a".

  1. Some languages will produce a compiletime error, asking you to clarify what you meant.
  2. Some languages will produce a runtime error because you can't add integers and strings
  3. Some languages will attempt to parse the string as number, and raise an error because "1a" is no valid decimal number
  4. Some languages will successfully parse the string, e.g. because they stop parsing at the first non digit
  5. Some languages will treat both as string and concatenate them.
  6. C will treat "1a" as a pointer to char and perform pointer arithmetic, returning "a".

Expressiveness of the type system

Things get more interesting once you consider complex types.

Different type systems allow you to express different ideas elegantly. They catch different errors at compile or runtime. They restrict you in different ways. They require different amounts of effort to learn.

Since each programmer and language designer weights those goals differently (or isn't even familiar with the advantages of some of them) we get a lot of different languages.

  • C has no convenient way to write a container that works with different types of elements. C++ has very powerful templates, but they add a lot of complexity to the language.
  • Go and Java both support interfaces. In java the class needs to explicitly implement an interface, in Go a type implicitly implements all interfaces matching its members. The Go approach allows a consumer to define the interfaces that fit its requirements, but it can produce false matches when a member has the same name, but different meaning.
  • Immutability simplifies reasoning about the code and enables sharing instances, but can make it inconvenient to manipulate your data.
  • Static typing catches many errors at compile time. But catching more errors increases the effort required to satisfy the compiler. Depending on how you express those compile time constraints you catch different errors. We're always looking for new type systems that find more errors or require less effort.
  • Rust has a type system that can prove that no two threads will unsafely modify a mutable object at the same time. But in exchange it requires meticulous ownership tracking, which many programmers will consider too inconvenient.
  • There are many features a language can offer, such as objects, multiple inheritance, deterministic destruction, memory safety, a GC, discriminating unions, higher order functions, generic containers/algorithms, operator overloading.

    Each is useful in some situations, but you need to weight them against the complexity of the language and thus the effort to learn it. Some features are even incompatible or at least interact badly with each other.

  • Generally good points, but could be improved. Playing a bit of "Devil's Advocate", neither of your examples is very compelling. Multiplying two huge numbers is a corner case in all systems. And 1 + "1a" makes no sense, as do the silly languages, (you know who you are! ), that try to parse it. :-)
    – user949300
    Commented Jan 30, 2016 at 2:44
  • 1
    @user949300: In C, "1a" is a pointer to a string literal, adding 1 to a pointer makes perfect sense, and char *foo = 1 + "1a"; is entirely valid (and is similar to char *foo = &"1a"[1]; and char *foo = "a";).
    – Brendan
    Commented Jan 30, 2016 at 9:02
  • @Brendan 1+"1a" makes for a nice obfuscated C contest, but would it survive any code review? IMO, talking about how languages handle foo.someUndefinedField, foo.someUndefinedMethod(), what is "true" and what is "false", or the possibly three kinds (are there more?) of "equals" would be far more relevant to realistic code.
    – user949300
    Commented Jan 30, 2016 at 15:22
  • 3
    @user949300: If you dismiss everything that might be used for an obfuscated C contest; you end up with a language where the only thing that's legal is comments, combined with a style guide that says "Don't use comments, the absence of code should be self explanatory".
    – Brendan
    Commented Jan 30, 2016 at 21:24

When I write + I just know that it is the addition operation.

And how do you know that? Because the semantics of the language say so!

By the way, that isn't even universally true. For example, for Strings in Java, + is not addition, but concatenation!

when I write int i;, I know that int is an integer and it is enough for me.

And how do you know what an integer is? The type system tells you!

By the way, that also isn't universally true. For example, in Java, int is not an integer but rather a member of the modulo ring ℤ232!

it is important to know what the difference beetwen static and dynamic, weak and strong type systems.

So, you say type systems are important, but then ask whether they are important?

  • Thank you for your answer! Ok, I see that type systems are importatnt. But is it nessessary to learn it at a deep level for all programmers? Or even for theoretican and compiler developers? We can understand difference beetwen static, dynamic, strong and weak type systems in two hours. But there are some large books about type systems.. Commented Jan 25, 2016 at 10:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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