The if Filter
The if filter allows conditional evaluation of a filter based on arbitrary criteria. The if filter is the only selection filter provided by CQLi, it has the form:
ifcondition [then] true-branch-filter [elsefalse-branch-filter]
The then keyword is optional. condition, true-branch-filter, and false-branch-filter are arbitrary filters.
When an if filter is reached, the condition is first evaluated. If the result of evaluating condition matches the position, the true-branch-filter filter is evaluated. Otherwise, if the optional else clause is provided, the false-branch-filter is evaluated.
The type and result of the if filter depends on whether an else clause is present and if so, whether the types of the true-branch-filter and false-branch-filter are the same. If no else clause is present, the if filter has Boolean type and yields true if the true-branch-filter filter matches the position or was not evaluated (because condition did not match the position). If an else clause is present and true-branch-filter and false-branch-filter have the same type, the result is the value of whichever of the two filters was evaluated, otherwise if true-branch-filter and false-branch-filter have different types, the result has Boolean type and matches the position if the evaluated filter matched the position.
| Example | Result | Explanation |
|---|---|---|
if 1 then 2 |
true |
if without else has Boolean type. |
if a1 then false |
false |
condition matches but branch filter does not. |
if false then false |
true |
if without else is true if condition does not match. |
if true then 2 else 3 |
2 |
Result has same type as then and else filters. |
if true then 2 else K |
true |
Result has Boolean type when then and else filters have different types. |
if filters may be nested, e.g. any of condition, true-branch-filter, or false-branch-filter may be, or contain, an if filter. For example:
if result "1-0" then comment "White won"
else if result "0-1" then comment "Black won"
else if result "1/2-1/2" then comment "Draw"
else comment "Incomplete"is equivalent to:
if result "1-0" then
comment "White won"
else
if result "0-1" then
comment "Black won"
else
if result "1/2-1/2" then
comment "Draw"
else comment "Incomplete"Iteration Filters
CQL provides several iteration filters that allow a target filter to be evaluated multiple times. The square filter evaluates its filter once for every square in a provided set, the piece iteration filter does the same for pieces residing on the set of provided squares. The key filter is used to iterate over all the keys in a dictionary. The while filter evaluates a specified filter until the provided condition does not match the position and the loop filter evaluates its target as long as it matches the position.
All of the iteration filters introduce a new variable scope that extends to the end of the filter.
The square Iteration Filter
square[all] VariableinSet-Expression Body
The square filter evaluates the Set-Expression one time and then iterates over the resulting squares, setting Variable to the value of the square before evaluating the Body. If the all parameter is specified, the result of the square filter has Boolean type and yields true if Body matched every iteration and false otherwise. When all is not specified, the result is the set of squares for which Body matched the position. If Set-Expression is an empty set, Body is never evaluated and the result of the square filter is true if all is specified and an empty set otherwise. The square iteration order is unspecified.
The query:
square all sq in d-e4-5 {
#A attacks sq > a attacks sq
}will evaluate to true if each center square has more white attackers than black attackers. Note that the Body of the above filter is equivalent to:
#(A attacks sq) > #(a attacks sq)because attacks has a higher precedence than # and a Set filter is implicitly converted to its cardinality when appearing in a comparison where the other side has Numeric type. To find all squares that are attacked by one side at least twice and defended by a fewer number of pieces on the other side, the following query can be used:
overdefended = flipcolor
square sq in . {
a attacks sq < A attacks sq > 1
}The piece Iteration Filter
piece[all] VariableinSet-Expression Body
The piece filter evaluates the Set-Expression one time and then iterates over the resulting squares on which a piece resides, setting Variable to the corresponding piece value before evaluating the Body. If the all parameter is specified, the result of the piece filter has Boolean type and yields true if Body matched every iteration and false otherwise. When all is not specified, the result is the set of squares for which Body matched the position. If Set-Expression is an empty set, Body is never evaluated and the result of the piece filter is true if all is specified and an empty set otherwise. The order in which pieces are iterated is unspecified.
The query:
piece pi in A {
#a attacks pi > A attacks pi
}will yield the set of squares on which underdefended white pieces are attacked by Black.
Note that any given piece filter:
pieceXinSetBody
can be expressed as the semantically equivalent square filter:
squareWinSet& [Aa] {
pieceX=W
Body
}
See Piece Tracking for more information on piece variables and piece identity.
The key and string Iteration Filters
keyVariableinDictionary-Name Body
stringVariableinDictionary-Name Body
The key filter evaluates Body one time for each key in the dictionary variable Dictionary-Name, setting the iteration variable Variable to the value of the current key before doing so. The key iteration order is unspecified.
The string filter operates the same way but only works for dictionaries having keys with String type. The string filter is provided for backwards compatibility.
The while Filter
while(Condition)Body
The while filter continually evaluates Condition and then Body as long as Condition matches the position.
If the Condition has the form String ~~ Pattern then the while filter has a regex-iteration form and the body is evaluated once for every portion of the String that matches Pattern as described here.
The result of the while filter has Boolean type and always matches the position unless it is the regex-iteration form and the LHS of the ~~ filter does not match the position.
Note that evaluation of the while filter will not complete until Condition fails to match the position. In particular, the loop will not be terminated because Body fails to match. If a loop variable is being used as part of the Condition, make sure that modifications to the loop variable occur as soon as possible in Body as an earlier filter that does not match the position will prevent the variable from being modified before the next loop iteration.
The loop Filter
loopBody
The loop filter continually evaluates Body until evaluation no longer matches the position.