Overview of static and dynamic typing

Alore is a programming language that supports both dynamic and static typing, and a mixture of both in the same program. This section gives an overview of some central issues related to static typing. We also discuss when to use static types, how static typing differs from dynamic typing, and why it can be very useful to have both static and dynamic typing available at the same time.

A dynamically-typed variable can hold values of any type (e.g. integers, strings or arrays). Operations on dynamically-typed variables are checked at runtime. In a dynamically-typed program all (or most) variables are dynamically typed.

Statically-typed variables are declared to hold values of a specific type. When using static typing, a program is type checked before running it. Type checking verifies that operations on a value are valid for the type of the value. For example, trying to add a string to an integer results in a type check error in a statically-typed program. In a dynamically-typed program the error would be caught only at runtime, and only when that particular operation would be performed.

This document assumes that the reader has a working knowledge of the dynamically-typed subset of Alore and the standard library, in particular the std module. It is sufficient to be familiar with the content of Introduction to Alore. This document focuses on the type system and does not repeat information in the linked general introduction.

It is helpful if the reader has a basic understanding of programming in a statically-typed language such as Java, C++ or C#.

A static typing example

In this section we present a small example program using both dynamic and static typing, and discuss their differences.

The following dynamically-typed program approximates two triangles using ASCII characters:

def Triangle(n, ch)
  for y in 0 to n
    WriteLn(ch * (y + 1))
  end
end
Triangle(2, '*')
Triangle(4, '\')

Now let's save the program as program.alo and run the program. The output looks like this:

$ alore program.alo
*
**
\
\\
\\\
\\\\

Declaring types

We can modify the program to be statically-typed by declaring the types of some variables. The as keyword is used to introduce these type annotations (we highlight all changes):

def Triangle(n as Int, ch as Str)
  for y in 0 to n
    WriteLn(ch * (y + 1))
  end
end
Triangle(2, '*')
Triangle(4, '\')

The annotations declare that Triangle must be called with a first argument that is an integer and a second argument that is a string. The annotations also declare the types of the arguments within the function body. The type of the local variable y is inferred to be Int. The output of the function remains identical to the dynamically-typed version.

We can also specify the type of y explicitly, by replacing the second line of the example with the line below:

for y as Int in 0 to n

Running the type checker

If you save the modified program as program2.alo, you can now type check it by running alore with the -c option:

$ alore -c program2.alo
$

There were no type errors since there was no output from the type checker. You can type check the program and also run it (if there are no errors) with the -t option:

$ alore -t program2.alo
*
**
\
\\
...

Introducing type errors

Now let's add a new line to the end of both of the program variants:

...
Triangle(2, '*')
Triangle(4, '\')
Triangle(3, 3)

The dynamically-typed program still produces some output, but perhaps not what we'd expect (and without reporting a problem):

$ alore program.alo
*
**
\
\\
\\\
\\\\
1
3
9

However, static type checking produces the following error when type checking the statically-typed program variant:

$ alore -c program2.alo
program2.alo, line 8: Argument 2 to "Triangle" has incompatible type "Int"

Let's do another modification:

...
Triangle(2, '*')
Triangle(4, '\')
Triangle('#', 3)

Note that the arguments in the third call are in reverse order. Now the dynamically-typed program terminates with a runtime type error after producing some output:

$ alore program3.alo
*
**
\
\\
\\\
\\\\
Traceback (most recent call last):
  at main level (program3.alo, line 8)
  Triangle (program3.alo, line 2)
TypeError: Non-integer Range upper bound (Str)

Static type checking again detects the above error without having to run the program:

$ alore -c program4.alo
program4.alo, line 8: Argument 1 to "Triangle" has incompatible type "Str"
program4.alo, line 8: Argument 2 to "Triangle" has incompatible type "Int"

The above examples highlight some of the differences between dynamic and static typing, although many details were omitted. The next section discusses the differences more broadly.

Note: Since Alore has an optional type system, you can always run programs that have type check errors. Simply omit the -c or -t option, and the interpreter will skip all type declarations. This can be very useful in the middle of a large program modification. It is nice to be able to debug a program with potentially hundreds of type errors in it, instead of being forced to wait until no type errors remain.

Why both static and dynamic typing?

At the present, almost all programming programming languages support only static or dynamic typing, or they clearly favor one of them. Alore is different in having excellent support for both of them. The philosophy of Alore is based on the observation that both dynamic and static typing are useful, but in different circumstances. These circumstances are always changing and difficult to predict, and it is undesirable to have to restrict oneself to one particular way. Alore gives the flexibility of choosing when static or dynamic typing is the right alternative, and the ability to switch between these when circumstances change. Alore does this without the hassle of having to support two different programming languages, with their different syntaxes, idioms, libraries and tools.

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.

Features of Alore type system

The list below presents some of the main features of the Alore type system. The rest of this document introduces these features in more detail:

More examples

The Alore distribution includes several example programs that show how to use static typing. Here are a few:

If you feel more adventurous, you can also have a look at Alore standard library module sources (under lib/) and the Alore type checker (under check/).