loop
The loop keyword offers a mechanism to repeat a short series of Envision
operations. The maximal number of iterations is 30. 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 30 (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 30
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 30.
Concat = ""
loop channel in ("Online", "Store", "Wholesale")
Concat = "\{Concat}\{channel}"
show scalar "" with Concat // OnlineStoreWholesale
The list can contain arbitrary expressions and tuple unpacking. As an extension
of the same form, loop ... in enum E iterates over the labels of a constant
enum table. The enum table must be non-empty and contain at most 30 values. The
iteration variable is a text value equal to the enum label.
The following example is equivalent to the explicit sequence above, but the sequence is provided by the enum table.
table enum Channel = "Online", "Store", "Wholesale"
Concat = ""
loop channel in enum Channel
Concat = "\{Concat}\{channel}"
show scalar "" with Concat // OnlineStoreWholesale
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.