In this tutorial, we’ll show the difference between typed and untyped programming languages.
We first discuss the use and role of types in programming languages. Then, we explain how typed languages differ from untyped ones.
2. Types and Values
A type is a set of values. For instance, we may have a type called “8-bit integer”. This is the set of all integers from -128 to 127. In other words, it is the set of all integer values that are composed of 8 bits. As another example, we may have a type called “8-bit character”. For instance, these may be letters of English alphabet, numerals, and some special characters.
2.1. Effect of Types
Having types in a programming languages has two main consequences:
- allowed operations on values
- interpretation of bit sequences
The first consequence is that values of a type support only the operations that apply to this type. Therefore, if we consider the integer type, then these operations will include addition, subtraction, etc. On the other hand, for the character type, the operations will include converting to upper case, for instance.
The other consequence is that a bit sequence, in memory for instance, has an interpretation that depends on this type. For instance, let’s consider the bit sequence 0010 1011. It is the value 43 if it has the type “integer”. However, the same bit sequence is the character `+’ if it has the type “character”.
2.2. Typed Languages
In a typed language, variables and values have types. There are languages that determine the types of variables in a program at compile-time. We call them statically-typed.
On the other hand, in some languages, we can only determine types of variables at runtime. We therefore call them dynamically-typed.
2.3. Static and Dynamic Typing
In statically-typed languages, when programmers declare variables, they have to explicitly assign them types. Moreover, it is usually an error to assign a value of some type to a variable of another type. Sometimes there are exceptions to this rule. These may exist, for instance, when a language allows conversions between some “compatible” types.
An example is the use of a value of type integer when a float (real number) is expected. In fact, mathematically, integers are a subset of real numbers.
In contrast, dynamically-typed languages allow the type of a variable to change as code is executing. Therefore, programmers do not have to explicitly assign a type to each variable. Instead, the runtime system of the language binds variables to types as the program’s code is executing.
3. Type Systems
Typed languages possess type systems which are sets of rules that deduce the type of each variable and expression.
Ultimately, the purpose of a type system is to detect errors that may result from the use of one type instead of another. In other words, type systems are used for type checking.
3.1. Type Checking
A language’s type system performs type checking by deducing the types of variables and expressions. In statically typed languages, compilers perform type checking at compile time.
On the other hand, in dynamically typed languages, the language’s runtime system performs type checking. As a result, in both cases, we detect typing errors. These are errors that result when the language’s type safety rules are violated.
3.2. Type Safety
The main purpose of type systems and, consequently, type checking is to help programmers detect errors in code. In this regard, type safety rules determine what the allowable operations are with respect to types.
For instance, we cannot assign a string value to a variable of type integer.
4. Untyped Languages
In untyped languages, there are no types. Alternatively, we can think of untyped languages as if they have a single universal type to which all values belong.
4.1. Effects Having No Types
When we have no types, we do not differentiate between values, i.e., all values belong to a single set. In other words, there are no restrictions when dealing with values and variables in a program.
Specifically, any value can be assigned to any variable. Moreover, any operation can be applied to any values or variables.
4.2. Examples of Untyped Languages
It is worth noting that some sources consider dynamically typed languages to be untyped. The reason for this is that, in dynamically typed languages, programmers do not have to explicitly specify a type when declaring a variable. However, we know that dynamically typed languages have types and type checking. In fact, at any instant during program execution, each variable has a type. Specifically, this type is determined by the runtime system of the language.
All high-level programming languages are typed; either statically or dynamically. The most notable example of untyped languages are assembly languages which deal directly with bit values in memory or registers. Even some assembly languages differentiate between floating point values (consequently operations) and other (integer) values. These ones can be considered to have two types.
In this tutorial, we talked about the difference between typed and untyped languages. We saw the usefulness of having types in a language and also the consequences of having no types.