The where ... 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.

expression1 where identifier is expression2
expression1 where identifier := expression2
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 for is. The scope of the identifier is the where ... is construction alone except for when the construction is part of an expression list --- see below.

The where operator is left-associative. This means that there can be multiple uses of where ... is constructions 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 are where ... is constructions 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.

The where operator also extends left in expression lists. That is, if there is an expression E in a expression list which is a where construction (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 State_where (H1E9)

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 where is 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 where constructions 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 where constructions 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 ]
V2.28, 13 July 2023