It might appear as a provocation that Lava abandons sequential loops, and many people will say perhaps that Lava will not be accepted by the majority of programmers for this reason.
On the other hand, mathematicians (like us) remember very well how surprised they were when they learned their first (procedural) programming language and had to write "do-, for-, repeat- or while-loops", instead of recursion, and mathematically provocative statements like "n = n+1".
Of course, all this is largely a matter of practice and habitude. We believe, however, that it will pay in the long run to abandon "multiple assignment", and, as a consequence, sequential loops, just as it pays to avoid "go to". The latter guarantees that the flow of control is essentially directed from top to bottom, except for cases where it returns to the beginning of a loop. Unfortunately, this remaining exception, where the control flow returns to the beginning of a loop, together with multiple assignment, may seriously obscure the data flow of a program:
Multiple assignment in a jungle of loops and branching statements: |
int x; while (...) if (...) while (...) { x = f(x,...); ... } else while (...) if (...) { x = g(x,...); // where has this value of x been assigned??? ... } else if (...) { x = h1(x,...); ... } else { x = h2(x,...); ... } |
On read access, the current value of "x" The data flow is obscured. |
In contrast to this, if we use recursive functions instead of loops and abandon multiple assignment, then the above "jungle" is decomposed into small functions and the data flow within each of the corresponding function bodies is directed strictly from top to bottom:
For every read access to a Lava variable you can easily find the origin of the current value of this variable by following the containing program branch in upward direction (unless the variable is an input variable and therefore a value is assigned to it already outside this function).
Summary: In Lava, both control flow and data flow are directed strictly from top to bottom.
The most important advantage of this combination of single-assignment and recursion in Lava, however, is that it enables perfect initialization checks for
In the following we present two categories of samples which are both related to iteration/recursion.
The Recursion samples illustrate how sequential loops can be replaced by tail recursion in a more or less mechanical way and how computationally inefficient forms of recursion, particularly tree recursion, can be transformed into tail recursion.
The Iterator/cursor/visitor samples show how certain aspects and details of aggregate/container objects can be hidden and separated from certain kinds of sequential algorithms that run through these data structures and process the contained items.
There is a kind of traditional loops that aren't inherently sequential since they don't forward information from one pass of the loop to the next. They could therefore be executed concurrently. They typically run through an index range or through the elements of a set and perform an exhaustive or a "stop when found" search. This kind of loops is expressed by "quantifiers" exist and foreach in Lava, as well as by the select expression which corresponds to the SQL select construct and is used to express set-oriented queries. The Quantifier sample presents a basic application of exist and foreach quantifiers and of set element handles.