A small number of built-in higher-order combinators are provided.
These include `map`, `reduce`, and `scan` and variants
on these to cater for reductions and scans with no base value.

The `scan` operators have been provided as primitive, in spite of it
being possible to define these in terms of list-homomorphisms. The
reason for this decision is that a more efficient parallel
implementation of `scan` exists than that furnished by the list
homomorphism.

In addition to the list processing primitives Adl provides the two
standard constructs of `if` and `while`. `if` caters
for conditional evaluation of an expression.
`while` is supplied as an iterator
to be used in cases where computation is not bounded by the length
of an input list.

The current version of Adl is non-recursive. The lack of recursion is convenient from the point of view of the language implementors since it allows all function calls to be in-lined and translated into composed sequences of functions in BMF. In the small number of Adl applications tested so far the lack of recursion has not caused us great difficulty, but further experiments on language expressiveness are underway.

Vectors are groupings of elements of the same type; they are
mapped by the compiler into BMF concatenate lists.
In Adl there are only
two means of creating vectors, the first is literal specification where
the vector is written as constant e.g. `[true,false,true,true]`.
The second is by the `iota` primitive which when given an integer
argument `n` it creates the integer vector: `[0,...,n-1]`.
This vector can be used to index another, or be directly transformed via
the list-primitives.
Two other vector operators are length, `#` and the infix operator
for indexing, `!`. Vector indices always start at 0.
Adl also possesses a number of primitives for arithmetic, type conversion,
boolean logic and specific mathematical operations. All of these operate
over the scalar data types.

add_rev(a:vof int,b:vof int) := let lb1 := #b-1; f x := a!x + b!(lb1-x); in map (f,iota #a) endlet

The main function must have the types of its input values declared. All other functions may, at the option of the programmer, have their types inferred by the compiler. If a function is used with more than one set of concrete types, separate instances of its definition are created by the type-checker. Access to elements of tuples is through pattern matching on the formal parameter of the function declaration.

In this program, access to elements of both lists is via vector indices
drawn from the call `iota #a`. The elements of the second list
are indexed in reverse-order. The result is a vector, the same length as
`a`, containing the sums of the elements pointed to by the indices.

Return to Adl project page