A functions that calls itself is a recursive functions. Recursive functions have the same structure as generic functions, with the only difference that the keyword fun replaces the keyword fn. An example of recursive function is a function to compute the Fibonacci value:

The function even tells if a number is even. The return value of even can be true, false, or the value returned by the call to even( n - 2 ). Because the return value of the call is returned without further processing, the recursive call to even( n - 2 ) is a tail recursive call.
Tail recursion is particularly important, because it allows, thanks to an approach known as tail call optimization, to be converted to loops. This means that there is no performance loss due to function calls, and tail recursion can be as fast as a for or while loop.

Recursive functions offer an elegant programming style, but they have a problem: for every call some data is put into the stack. This means that potentially, when the recursive function calls itself a lot of times, a stack overflow exception occurs. Tail recursion has theoretically the same problem, however, because of tail call optimization, the problem doesn't occur in practice; tail recursive functions are stack overflow free.
Considering the privileged status of tail recursion, an obvious question is whether it is possible to always use recursive functions instead of non-recursive ones. It turns out that any algorithm is implementable with tail recursion by adding extra parameters, called accumulators, to the recursive function. The purpose of these parameters is to accumulate information from the previous calls (hence the name), and carry it across different recursive calls.
For example, considering the code to implement the factorial:

This is an obvious implementation of the factorial, and it's recursive, but not tail recursive. To create a tail recursive version we add an accumulator to our function; this accumulator will contain the value of the factorial calculated so far:

Control Flow in ATS, like in other functional programming languages, is mostly implemented in a different way from languages that follow structured programming. But there is a classic construct that has exactly the same structure in ATS as in imperative languages: if - then - else. The general structure is:

A binding is a constant value that is defined using the result of an expression. It can be compared to const in C/C++ or final in Java. A binding in ATS is declared using the keyword val. Example of bindings could be val foo = 1 or val bar = 2 * 2. The name binding comes from the fact that we bind the names foo and barto the expressions 1 and 2 * 2. A binding can also be defined using other bindings:

val x = 10
val square = x * x

In this case x will obviously be initialized before square.
Note that the bindings declared don't have a type. In fact, a binding declared with val will take its type from the expression it is bound to. It is possible to be more strict, and explicitly set a type for a binding. For example, the binding val pi = 3.14 defines a double, as the expression 3.14 is by default a double. If we write val pi = 3.14f then pi will be a float. It is possible to say that pi must be a float in any case, by saying val pi: float = 3.14. If you assign an incompatible type, for example, in val pi: char = 3.14, a compilation error will occur.
A similar, but slightly different, situation, is the assignment of a type not to a binding but to an expression. This can be achieved by writing something like val pi = 3.14: float. In this case the float type is given to the expression. So, while at the end our binding will always be a float, the process is slightly different.

Bindings are visible within some specific boundaries. These boundaries define the scope of the binding. Within the scope, the binding can be declared, initialized, and used.
The highest level for a scope is the top level: at this level the binding is not located within a function, and it is visible in all points of a file, starting from the point where the binding is declared:

We can't use pi from area, so our implementation is an error; but we can use it from circle.
At a lower level we have local bindings, which are defined within a segment of code. Local bindings can be used in two ways.
The first way is as a help to evaluate expressions. In this case the name used in the binding can be used to form other expressions. The generic structure in this case is:

What we have in this case it that the different names name_1,...,name_n are used to evaluate the expression expression_to_evaluate. That is, the bindings are valid between the in and the end. For example: