loop
The loop keyword offers a mechanism to repeat a short series of Envision
operations. The maximal number of iterations is 10. This low maximum is
intentional as arbitrary loops introduce problems that are better solved
through the other constructs of the Envision language.
loop (n : number), code block
The loop keyword takes a single argument which must be an integer constant
between 1 and 10 (inclusive).
The count may be any constant expression.
a = 1
loop 3
b = a + 1
a = 2 * b
show summary "" with a, b // 22, 11
loop does not introduce a new scope; variables defined inside remain visible.
The block is a macro expansion repeated n times.
loop (n : number) in (low : number) .. (high : number), code block
The loop keyword defines an iteration variable over a range of integer
values. The boundaries are inclusive, and must contain between 1 and 10
values.
s = 0
loop n in 11 .. 15
s = s + n
show summary "" with s // 65
loop (n : number) in sequence, code block
The loop keyword defines an iteration variable over an explicit list of
values. The list length (and thus the iteration count) is capped at 10.
msg = ""
loop n in ("h", "e", "l", "l", "o")
msg = concat(msg, n)
show summary "" with msg // 'hello'
The list can contain arbitrary expressions and tuple unpacking.
Values = ("B", "C", "D")
Concat = ""
loop V in ("A", ...Values, "E")
Concat = "\{Concat}\{V}"
show scalar "" with Concat // ABCDE
loop (F : flagset) subset flags(…), code block
The loop keyword can iterate over all subsets of a constant flagset returned
by flags(...). The iteration variable F is a flagset. The loop includes the
empty set and the full set. The number of iterations is 2^k, where k is the
number of flags. At most 16 iterations are allowed (a flagset size of 4).
table Orders[o] = with
[| as o, as Color, as Size, as Brand, as Qty |]
[| 1, "Red", "S", "A", 2 |]
[| 2, "Blue", "M", "B", 1 |]
table OrdersCube = with
loop F subset flags(0, 1, 2)
[| if contains(F, 0) then Orders.Color else "All" as Color,
if contains(F, 1) then Orders.Size else "All" as Size,
if contains(F, 2) then Orders.Brand else "All" as Brand,
o as o,
Orders.Qty as Qty |]
show table "OrdersCube" with
OrdersCube.Color
OrdersCube.Size
OrdersCube.Brand
OrdersCube.o
OrdersCube.Qty
Restrictions
loop blocks cannot include import, def, read, write, or nested
loop statements. Stand-alone show statements are also forbidden. Table
declarations are allowed only when they re-apply a filter to the same table
across iterations.
a = 10
b = 0
table T = extend.range(10)
loop 3
a = a - 1
table T = where T.N < a
b = b + sum(T.N)
loop can be used inside table comprehensions:
table T = with
[| as A |]
loop N in 1..3
[| N |]
loop can also be used inside show ... with bodies. In that context, each
iteration contributes columns or tile-specific sub-blocks to the surrounding
tile rather than introducing nested show statements. This pattern is useful
for monthly reports, where one loop iteration can produce one month column.
keep span date = [date(2024, 1, 1) .. date(2024, 6, 30)]
table Items[item] = with
[| as item |]
[| "shirt" |]
[| "hat" |]
table Sales = with
[| as Item, as Date , as Qty |]
[| "shirt", date(2024, 1, 15), 120 |]
[| "shirt", date(2024, 2, 15), 140 |]
[| "shirt", date(2024, 3, 15), 135 |]
[| "shirt", date(2024, 4, 15), 150 |]
[| "shirt", date(2024, 5, 15), 155 |]
[| "shirt", date(2024, 6, 15), 160 |]
[| "hat" , date(2024, 1, 15), 80 |]
[| "hat" , date(2024, 2, 15), 95 |]
[| "hat" , date(2024, 3, 15), 110 |]
[| "hat" , date(2024, 4, 15), 105 |]
[| "hat" , date(2024, 5, 15), 115 |]
[| "hat" , date(2024, 6, 15), 125 |]
table Monthly[key] = by [Sales.Item, month(Sales.Date)]
Monthly.Item, Monthly.Period = key
Monthly.Qty = sum(Sales.Qty)
latest = max(Month.month)
show table "Last 6 months" with
item as "Item"
loop k in 0..5
Monthly.Qty[item, latest - 5 + k] as text(latest - 5 + k)
See show for the general rules that apply inside tile bodies.