expect
The keyword expect is used in Envision to indicate that a variable abides to a certain rule.
’expect table tbl max tblSize’, cap on table size
A cap on the size of a table can be enforced at runtime via the expect statement:
n = 500
table T = extend.range(n) // 'T.N' goes from 1 to 50 (inclusive)
expect table T max 100 // the line fails of 'n' is greater than 100
show table "" with T.N // Runtime error: Table 'T' has 500 lines, maximum was 100.
Capping the size of a table is frequently done to very distinct reasons in Envision.
- Some Envision capabilities only work with tables below a given limit. The script will not compile until the constraint is acklowledged explicitly in the script. This behavior improves the overall correctness-by-design in mitigating “surprising” shortcomings of Envision on specific operations that are not scalable (for example due to quadratic complexity).
- Sometimes, certain tables are genuinely expected to remain relatively small (ex: the number of locations), and a large number of lines indicates that something went wrong somewhere. Capping the size of the table is useful to stop the process early, closer to the root cause of the problem.
expect table also supports a minimum size:
table T = extend.range(3)
expect table T min 2
expect table T max 5
show table "" with T.N
The size check can be placed inside filters to assert the size of the filtered table:
table T = extend.range(3)
where T.N == 1
expect table T max 1
Numeric suffixes are supported for size values: k, m, and b. Read statements, non-partitioned path schemas, and table comprehensions default to min 1; other tables default to min 0.
’expect T.dim = U.other’, add a secondary dimension to a table
A secondary dimension cna be added at runtime to a table:
table T[id] = with // 'id' is the primary dimension of 'T'
[| as id |]
[| "id0" |]
[| "id1" |]
table U = with
[| as RefToId, as Variant |]
[| "id0", "black" |]
[| "id0", "white" |]
[| "id1", "black" |]
[| "id1", "white" |]
[| "id1", "green" |]
// Add 'id' as a secondary dimension to table 'U'.
// This line would fail at runtime if there was a 'U.RefToId' value mismatching 'id'.
expect U.id = U.RefToId
show table "Counts the variants" with
T.id as "Id"
count(U.*) into T as "Count" // 'U' is upstream of 'T', thus 'U' can be aggregated into 'T'
// Id,Count
// id0,2
// id1,3
expect T.dim = expr requires dim to be the name of an existing primary dimension. The check is enforced at runtime; any unmatched value causes a failure.
‘read path as tbl expect [dim] with’, add a secondary dimension via a read
A secondary dimension be declared while reading a table with expect. The dimension itself must appear first in another table.
read "/products.csv" as Products[Id] with // 'Id' is the primary dimension of 'Products'
Id : text
Name : text
read "/variants.csv" as Variants expect [Id] with // 'Id' is a secondary dimension of 'Variants'
Id : text
Color : text
At runtime, Envision will check that all the values Variants.Id are found in Products.Id. If an unknown identifiier is encountered in variants.csv, then the execution of the script will fail.
‘read path as T[dim]’, primary dimension
A primary dimension can be declared in a read statement. Values must be unique.
read "/sample/products.csv" as Products[product] with
"Product" as product : text
Price : number
If a primary dimension name does not match any column, Envision generates an ordinal identifier:
read "/sample/products.csv" as Products[id] with
Product : text
Price : number