The where \(\ldots\) is Construction#
By the use of the where ... is construction, one can within an expression temporarily assign an identifier to a sub-expression. This allows for compact code and efficient re-use of common sub-expressions.
- expression₁ where identifier is expression₂#
- expression₁ where identifier := expression₂#
This construction is an expression that temporarily assigns the identifier to the second expression and then yields the value of the first expression. The identifier may be referred to in the first expression and it will equal the value of the second expression. The token
:=can be used as a synonym foris. The scope of the identifier is thewhere ... isconstruction alone except for when the construction is part of an expression list — see below. Thewhereoperator is left-associative. This means that there can be multiple uses ofwhere ... isconstructions and each expression can refer to variables bound in the enclosing constructions. Another important feature is found in a set or sequence constructor. If there arewhere ... isconstructions in the predicate, then any variables bound in them may be referred to in the expression at the beginning of the constructor. If the whole predicate is placed in parentheses, then any variables bound in the predicate do not extend to the expression at the beginning of the constructor. Thewhereoperator also extends left in expression lists. That is, if there is an expression \(E\) in a expression list which is awhereconstruction (or chain of where constructions), the identifiers bound in that where construction (or chain) will be defined in all expressions in the list which are to the left of \(E\). Expression lists commonly arise as argument lists to functions or procedures, return arguments, print statements (with or without the word ‘print’) etc. A where construction also overrides (hides) any where construction to the right of it in the same list. Using parentheses around a where expression ensures that the identifiers bound within it are not seen outside it.
- Example: where (ex-f8d9ed)#
The following examples illustrate simple uses of
where ... is.> x := 1; > x where x is 10; 10 > x; 1 > Order(G) + Degree(G) where G is Sym(3); 9
Since
whereis left-associative we may have multiple uses of it. The use of parentheses, of course, can override the usual associativity.> x := 1; > y := 2; > x + y where x is 5 where y is 6; 11 > (x + y where x is 5) where y is 6; // the same 11 > x + y where x is (5 where y is 6); 7 > x + y where x is y where y is 6; 12 > (x + y where x is y) where y is 6; // the same 12 > x + y where x is (y where y is 6); 8
We now illustrate how the left expression in a set or sequence constructor can reference the identifiers of
whereconstructions in the predicate.> { a : i in [1 .. 10] | IsPrime(a) where a is 3*i + 1 }; { 7, 13, 19, 31 } > [ <x, y> : i in [1 .. 10] | IsPrime(x) and IsPrime(y) > where x is y + 2 where y is 2 * i + 1 ]; [ <5, 3>, <7, 5>, <13, 11>, <19, 17> ]
We next demonstrate the semantics of
whereconstructions inside expression lists.> // A simple use: > [a, a where a is 1]; [ 1, 1 ] > // An error: where does not extend right > print [a where a is 1, a]; User error: Identifier 'a' has not been declared > // Use of parentheses: > [a, (a where a is 1)] where a is 2; [ 2, 1 ] > // Another use of parentheses: > print [ a, (a where a is 1) ]; User error: Identifier 'a' has not been declared > // Use of a chain of where expressions: > [ <a, b>, <b, a> where a is 1 where b is 2 ]; [ <1, 2>, <2, 1> ] > // One where overriding another to the right of it: > [ a, a where a is 2, a where a is 3 ]; [ 2, 2, 3 ]