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_1 where identifier is expression_2
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 scope of the identifier is the where ... is construction alone.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.
> x := 1; > print x where x is 10; 10 > print x; 1 > print Order(G) + Degree(G) where G is Sym(3); 9Since 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; > print x + y where x is 5 where y is 6; 11 > print (x + y where x is 5) where y is 6; // the same 11 > print x + y where x is (5 where y is 6); 7 > print x + y where x is y where y is 6; 12 > print (x + y where x is y) where y is 6; // the same 12 > print x + y where x is (y where y is 6); 8We also illustrate how the left expression in a set or sequence constructor can reference the identifiers of where ... is constructions in the predicate.
> print { a: i in [1 .. 10] | IsPrime(a) where a is 3*i + 1 };
{ 7, 13, 19, 31 }
> print [<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> ]