# 10. Execution Control¶

## 10.0 Overview¶

Basic function application in q provides sequential evaluation of a series of expressions. In this chapter we demonstrate how to achieve non-sequential execution in q.

## 10.1 Control Flow¶

When writing vector operations in q, the cleanest code and best performance is obtained by avoiding loops and conditional execution. For those times when you simply must write iffy or loopy code, q has versions of the usual constructs.

Warning

Control flow constructs in this section involve branching in the byte code generated by the q interpreter. The offset of the branch destination is limited (currently to 255 byte codes), which means that the sequence of q expressions that can be contained in any part of $, ?, if, do, or while must be short. At some point, insertion of one additional statement will break the camel’s back, resulting in a 'branch error. This is q's way of rejecting bloated code. In this situation, factor code blocks into separate functions. Better yet, restructure your code. ### 10.1.1 Basic Conditional Evaluation¶ Languages of C heritage have a form of in-line if, called conditional evaluation, of the form, exprcond ? exprtrue : exprfalse where exprcond is an expression that evaluates to a Boolean (or int in C and C++). The result of the expression is exprtrue when exprcond is true (or non-zero) and exprfalse otherwise. The same effect can be achieved in q using the triadic overload of$.

$[exprcond; exprtrue; exprfalse] Here exprcond is an expression that evaluates to a boolean atom. Analogous to C, the result of exprcond can be any type whose underlying value is an integer. The result of the conditional is the evaluation of exprtrue when exprcond is not zero and exprfalse if it is zero. q)$[1b;42;9*6]
42
q)$[0b;42;9*6] _ Tip The conditional$ is a function that always returns a value. It is good practice for exprtrue and exprfalse to have the same type. This is not enforced in q as it is in statically-typed functional languages.

The brackets in any q conditional do not create lexical scope. This means that variables created within the body exist in the same scope as the conditional. For example, in a fresh q session the variable a in the following is a global that persists outside the conditional.

q)a
'a
q)$[1b;a:42;a:43] 42 q)a 42 Although evaluation of function arguments in q is eager, evaluation of the expressions in the conditional is short circuited, meaning that only the one selected for return is evaluated. Again in a fresh q session, q)a 'a q)b 'b q)$[1b;a:42;b:43]
42
q)a
42
q)b
'b

Observe that a test for zero in exprcond is redundant: remove that test and reverse the order of the second and third arguments.

q)z:0
q)$[z=0;1.1;-1.1] 1.1 q)$[z;-1.1;1.1] / equivalent to previous
1.1

In contrast with earlier versions of q, some null values are now acceptable for exprcond. It is the same as testing for null with the operator null.

q)v:0N
q)$[v;isnull;notnull] isnull q)$[null v;isnull;notnull]
_

Tip

Float nulls do not work so the above is probably an accident and you should not count on it.

### 10.1.2 Extended Conditional Evaluation¶

In languages of C heritage, the if-else statement has the form,

if (expr_cond) {
statement_true1;
.
.
.
}

else {
statement_false1;
.
.
.
}

where expr_cond is an expression that evaluates to a boolean (or int in C and C++). If the expression expr_cond is true (i.e., non-zero) the first sequence of statements in braces is executed; otherwise, the second sequence of statements in braces is executed.

A similar effect can be achieved in q using an extended form of conditional evaluation with $.$[exprcond; [exprtrue1; …]; [exprfalse1; …]]

where exprcond is an expression as in the basic conditional. When exprcond evaluates to non-zero, the first bracketed sequence of expressions is evaluated in left-to-right order; otherwise, the second bracketed sequence of expressions is evaluated.

q)v:42
q)$[v=42; [a:6;b:7;Everything]; [a:Life;b:the;c:Universe;a,b,c]] Everything q)$[v=43; [a:6;b:7;everything]; [a:Life;b:the;c:Universe;a,b,c]]
LifetheUniverse

The extended forms of the conditional are still functions with return values. If you are using them strictly for side effects, you are writing imperative, non-vector code and should consider VBA as an alternative.

Languages of C heritage have a cascading form of if-else in which multiple tests can be made,

if (expr_cond1) {
statement_true11;
.
.
.
}
else if (expr_condn) {
statement_truen1;
.
.
.
}
.
.
.
else {
statement_false;
.
.
.
}

In this construction, the expr_condn are evaluated consecutively until one is true (non-zero), at which point the associated block of statements is executed and the statement is complete. If none of the expressions passes, the final block of statements, called the default case, is executed.

A similar effect can be achieved in q with another extended form of conditional execution.

$[exprcond1;exprtrue1; …;exprcondn;exprtruen;exprfalse] In this form, the conditional expressions are evaluated consecutively until one is non-zero, at which point the associated exprtrue is evaluated and its result is returned. If none of the conditional expressions evaluates to non-zero, exprfalse is evaluated and its result is returned. Observe that exprfalse is the only expression that is not part of a pair, as it has no guarding conditional expression. Tip Any condition other than the first is only evaluated if all those prior to it have evaluated to zero. Otherwise put, a condition evaluating to non-zero short-circuits the evaluation of subsequent ones. q)a:0 q)$[a=0;zero; a>0;pos; neg]
zero
q)a:42
q)$[a=0;zero; a>0;pos; neg] _ q)a:-42 q)$[a=0;zero; a>0;pos; neg]
_

Finally, the previous extended form of conditional execution can be further extended by substituting a bracketed sequence of expressions for any exprtrue or exprfalse.

KDB+ 3.2 …
q)
1000000

### 10.3.2 Blocks¶

You can comment out a block of code (i.e., multiple lines) in a script by surrounding it with matching / and \ with each at the beginning of its own line. An unmatched \ at the beginning of a line exits the script.

Here is a script that demonstrates block comments.

a:42
b:0
/
this is a block of
comment text
b:42
and b will not be changed
\
a:43 / this line will be executed
\
nothing from here on will be executed
b:44

Immediately after this script is loaded, a will be 43 and b will be 0.

Multi-line expressions are permitted in a script but they have a special form.

• The first line must not be indented – i.e., it begins at the left of the line with no initial whitespace.
• Any continuation lines must be indented, meaning that there is at least one whitespace character at the beginning of the line.
• In particular, if you put the closing brace to a function definition on its own line, it must be indented. Do not use the common C style of aligning the closing brace with the function name.
• Empty lines and comment lines (beginning with /) are permitted anywhere.

Table definition and function definition provide nice opportunities for splitting across multiple lines:

• A table can have line breaks after a closing square bracket ] or after a semicolon separator ;
• A function can have line breaks after a closing square bracket ] or after a comma separator ,.

### 10.3.3 Passing Parameters¶

Parameters are passed to a q script at q startup similarly to argv command line parameters in C. Specifically, the system variable .z.x comprises a list of strings, each containing the character representation of an argument present on the command line that invoked the script. For example, let’s modify our trades.q script to pass the number of records to be created as a command line parameter. Note that we parse the passed string to an integer.

dt:2015.01.01+sz?31;
tm:sz?24:00:00.000;
sym:sz?tickers;
qty:10*1+sz?1000;
px:90.0+(sz?2001)%100;
t:([] dt; tm; sym; qty; px);
t:dttm xasc t;
t:update px:6*px from t where sym=goog;
t:update px:2*px from t where sym=ibm;
t}

size:"I"\$.z.x 0

trades:mktrades[aaplgoog`ibm; size]

Now we invoke the script with the parameter 2000000.