forall - Execute a sequence of statements according to an expression template.
forall (expr) { stmts }
expr must be an array index expression, a dictionary lookup expression, or an object public reference expression. The accessors (indexes or reference variables) of expr must be simple variable names.
The following forms are allowed for expr:
The index, index-list, key, or ref accessors must be simple variable names, and are declared by their inclusion in the forall statement.
Any statement may be included in stmts. Each stmt
may refer to the variables declared by the expr accessors. The
stmt may also refer to the base array, dict, or object by
using the ?*
pseudo-constant. This is
especially useful if the base was produced by an expression.
The expr dictates the loop bounds, as follows:
expr template | Loop bounds |
---|---|
arr[index] | 0 to arr.length() - 1 |
arr[index-list] | [0,0,0,...] to arr.shape() - 1 (see Note 1) |
arr#[index] | 0 to arr.sizeof() - 1 |
dict[key] | All keys of dict (see Note 2) |
obj.(ref) | All public variables of obj |
Note 1: In the arr[index-list] case, the number of indexes N may be fewer than the rank of arr. In this case, only the first N components of the shape of arr dictate the loop bounds. In a multi-dimentsional index-list, the right-most index iterates the fastest.
Note 2:An unused entry in a dictionary will have a key of nil.
Each statement in stmts must be terminated by a semicolon.
The order of iterations of the elements of objects and dictionaries is not deterministic; it may vary from compile-to-compile, and may even vary depending on the contents of the dictionary.
Note that forall is a statemment; contrast it with foreach which is an expression.
a = [2,3].iterate() // A single index iterates over the length of the base forall (a[i]) { "Row ", i, '\n'; } Row 0 Row 1 // Two indexes iterate over the shape of the base forall (a[i,j]) { "", i, ", ", j, (j == 2) ? '\n' : "; "; } 0, 0; 0, 1; 0, 2 1, 0; 1, 1; 1, 2 // A flat index iterates over the sizeof the base forall (a#[i]) { var b = Char('a'+i); "", b, (i == 5) ? '\n' : ' '; } a b c d e f // Use the ?* constant to refer to the base array forall (((a+1)*10)[i,j]) { var b = ?*[i,j]; "", b, (j == 2) ? '\n' : ' '; } 10 20 30 40 50 60 // Attempting to access more elements than present in the array // throws a ShapeCheck error forall(a[i,j,k]) { "Not printed."; } Inconsistent array shape // The expression and accessor may be a dictionary lookup a = <<<"Red", 1, "Green", 2, "Blue", 3>>>; forall (a[i]) { "", i, ": ", a[i], '\n'; } Red: 1 Green: 2 Blue: 3 a = new Dict(4) a["Red"] = 1; a["Green"] = 2; a["Blue"] = 3; forall (a[i]) { "", i, ": ", a[i], '\n'; } Red: 1 Green: 2 Blue: 3 nil: nil // The expression and accessor may be an object lookup class foo {public var x = 3, y = 4;} foo bar() forall (bar.(i)) { "bar.", i, " = ", bar.(i), '\n'; } bar.parent = foo bar.x = 3 bar.y = 4 // The accessor variables are declared by the forall statement; // if the variable is already declared, a warning is issued a = [2,3].iterate() index = "hello" forall (a[index]) { Warning: Local name index hides outer declaration "", index, '\n'; } 0 1 index hello