function
CQL has a primitive function facility. A function filter has the following elements in order:- The keyword
function
- A variable name, the name of the function
- An argument list, which is a sequence of variable names enclosed in parentheses. These variables are called the formal parameters of the function
- A compound filter, called the body of the function.
Examples of functions:
function mate_or_stalemate() { mate or stalemate }function PurePieces(z) { z&[RBNQrbnq] }
function double(x) { 2*x }
function sets_smaller(x y){ #x<#y }
Function calling
A function is called by putting its actual arguments in parentheses after the name of the function. The number of arguments must equal the number of formal parameters of the function. The i'th formal parameter is said to correspond to the i'th actual argument (and vice versa).
For example, if the above functions are defined, then the following code matches a position that is mate or stalemate:
mate_or_stalemate()
The value of a function call is whatever the value of its body is when invoked with the arguments:
comment("The number of squares on a chessboard is: " double(#a-d1-8));
The code below matches a position in which there are more rooks than queens
sets_smaller ([Qq] [Rr])In the above call, the formal parameters of
double
are x
and y
. The corresponding actual arguments are [Qq]
and [Rr]
respectively.
Invocation of a function is performed as follows:
- For each actual argument z of the function call:
- If z is a variable then the corresponding variable of z is z
- Otherwise, z is assigned to a new, unique variable Z which is called the corresponding variable for z.
- The body of the function is modified as follows: each occurrence of a formal parameter w in the body corresponding to an argument z of the function call is renamed to be the corresponding variable for z
- The modified body of the function is evaluated in place of the function call
sets_smaller([Qq] [Rr])
, the modified body might look like this:
{CQL_var_1=[Qq] CQL_var_2=[Rr] {#CQL_var_1<#CQL_var_2}}
Note that as a consequence of these rules:
- If a formal parameter is assigned a value in the function body, and if the corresponding actual argument is a variable, then the value of the actual argument will be changed.
- If an actual argument is a piece variable, and if the current position in the function body is modified, the value of the corresponding formal parameter will reflect the value of the actual argument piece variable in that current position. However, if the actual argument is a set variable, the value of its corresponding formal parameter will not vary according to the current position.
- Direct or indirect function recursion is not allowed (and will crash CQL if attempted).
- There is no time penalty associated with function invocation.
Notes on using strings with functions
Be careful not to inadvertently change the value of a string parameter passed to a function. Consider a function that changes the first character of its string parameter to a "a", and returns the new stringfunction ChangeA (z){ z[0]="a" z}
Thus,
ChangeA("bfile")=="afile"
If the actual argument to ChangeA
is a variable, the value of the variable will be changed as well:
x="bfile" ChangeA(x)=="afile" x=="afile"
If this is unwanted, enclose the actual parameter in parentheses or braces:
x="bfile" ChangeA((x))=="afile" x=="bfile"Currently in CQL, it can be more efficient, for large strings, to pass arguments in variables, since extra copies are avoided.
Moreover, in the above, just
ChangeA(x)
would fail to compile. This is because the body of ChangeA
becomes
{x[0]="a" x}The value of the last
x
is never used, so CQL warns that this might be an error (which in fact is reasonable here, since the function is written as if its value matters but the value is ignored).
Using transforms with functions
A transform operator, likeflipcolor
, does not affect the function definition. However, it does modify the function call. That's because function calls textually replace the call with the function body, and that replacement can be transformed like any other CQL code.
Examples
Thefunction
filter is used in averagedistance.cql.