# 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 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: where (ex-f8d9ed)`

The following examples illustrate simple uses of `where ... is`.

```magma
> 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.

```magma
> 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.

```magma
> { 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.

```magma
> // 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 ]

```
