Iterating with 'loop'
A loop
block repeats a block of Envision code. The number of iterations is passed as an integer after the loop
keyword. The value of the integer must be between 2 and 10 (inclusive). The following script illustrates the loop
block:
a = 1
loop 3
// (a, b) is (4, 2) after the 1st iteration,
// (10, 5) after the 2nd iteration,
// (22, 11) after the 3rd iteration
b = a + 1
a = 2 * b
show summary "" with a, b // 22, 11
Advanced remark: The loop
is similar to a strongly-typed code macro-expansion. Under the hood, the Envision code is treated as if it had been copy-pasted that many times. This explain why Lokad sets a low limit at 10.
Unlike most blocks in Envision, a loop
block does not involve any scoping. Hence, in the script above, the variable b
remains accessible after exiting the loop
block.
This script could have been equivalently written:
a = 1
b = a + 1 // 1st iteration
a = 2 * b
b = a + 1 // 2nd iteration
a = 2 * b
b = a + 1 // 3rd iteration
a = 2 * b
show summary "" with a, b // 22, 11
Constant iteration count
The loop iteration count does not need to be a literal, it can be any constant expression (although it will report an error if the constant value is less than 1 or more than 10):
const iteration = 1 + today() - monday(today())
const day = "Sunday"
loop iteration
day = match day
"Sunday" -> "Monday"
"Monday" -> "Tuesday"
"Tuesday" -> "Wednesday"
"Wednesday" -> "Thursday"
"Thursday" -> "Friday"
"Friday" -> "Saturday"
"Saturday" -> "Sunday"
show label "Today" with day
Iteration lists
It is also possible to loop through a list of values, using loop VAR in (EXPR, EXPR)
syntax:
All = ""
loop Letter in ("A", "B", "C", "D")
All = "\{All}\{Letter}"
This is expanded to:
All = ""
Letter = "A"
All = "\{All}\{Letter}"
Letter = "B"
All = "\{All}\{Letter}"
Letter = "C"
All = "\{All}\{Letter}"
Letter = "D"
All = "\{All}\{Letter}"
The maximum number of values (and iterations) is still 10.
The list of values can contain arbitrary expressions (it is not limited to only literals, or even scalars).
table T = extend.range(10)
S = 0
loop T.X in (T.N, T.1, log(T.N) + 2)
S = S + sum(T.X)
Tuples can be unpacked in the list of values. The example below behaves exactly as if if the list had been "A", "B", "C", "D"
.
All = ""
BC = ("B", "C")
loop Letter in ("A", ...BC, "D")
All = "\{All}\{Letter}"
Iteration ranges
If the list of values is a range of numbers, then a shorter syntax also exists:
Sum = 0
loop N in 1 .. 5
Sum = Sum + N
This is equivalent to:
Sum = 0
loop N in (1, 2, 3, 4, 5)
Sum = Sum + N
Restrictions over block contents
loop
blocks cannot include any import
, def
, show
, read
or write
statements, nor can they include nested loop
blocks.
They can include table declarations under certain conditions, as illustrated by the following example:
a = 10
b = 0
table T = extend.range(10)
loop 10
a = a - 1
table T = where T.N < a
b = b + sum(T.N)
show summary "" with a, b // 0, 120
In the above script, the repeated declarations of the table T
are valid because they are filters iteratively applied over the same table.
Loops can also be used inside a table comprehension:
table T = with
[| as A |]
loop N in 1..10
[| N |]
show table "T" with T.A
This displays a table with a single “A” column containg the values 1 to 10.