Controlling evaluation

' ': /: \: each peach prior $[x;y;z] Cond \ / scan over ?[x;y;z] Vector Conditional

.[f;x;e] Trap : Return do exit @[f;x;e] Trap-At ' Signal if while

Evaluation is controlled by

  • iterators (maps and accumulators) for iteration
  • conditional evaluation
  • explicit return from a lambda
  • signalling and trapping errors
  • control words

Debugging

Iterators

Iterators are the primary means of iterating in q.

Maps

The maps Each, Each Left, Each Right, Each Parallel, and Each Prior are iterators that apply values across the items of lists and dictionaries.

Accumulators

The accumulators Scan and Over are iterators that apply values progressively: that is, first to argument/s, then progressively to the result of each evaluation.

For unary values, they have three forms, known as Converge, Do, and While.

Case

Case control structures in other languages map values to code or result values. In q this mapping is more often handled by indexing into lists or dictionaries.

q)show v:10?`v1`v2`v3               / values
`v1`v1`v3`v2`v3`v2`v3`v3`v2`v1
q)`r1`r2`r3 `v1`v2`v3?v             / Find
`r1`r1`r3`r2`r3`r2`r3`r3`r2`r1
q)(`v1`v2!`r1`r2) v                 / dictionary: implicit default
`r1`r1``r2``r2```r2`r1
q)`r1`r2`default `v1`v2?v           / explicit default
`r1`r1`default`r2`default`r2`default`default`r2`r1

The values mapped can be functions. The pseudocode

for-each (x in v) {
    switch(x) {
    case `v1:
        `abc,x;
        break;
    case `v2:
        string x;
        break;
    default:
        x;
    }
}

can be written in q as

q)((`abc,;string;::) `v1`v2?v)@'v
`abc`v1
`abc`v1
`v3
"v2"
`v3
"v2"
`v3
`v3
"v2"
`abc`v1

and optimized with .Q.fu.

See also the Case iterator.

Conditional evaluation

Syntax: $[x;y;z]

Cond returns z when x is zero; else y.

Two arguments are evaluated: x and either y or z.

Vector Conditional does something similar for lists of arguments, but evaluates all three arguments. It should be used in qSQL queries, which do not support Cond.

Explicit return

Syntax: :x

The result of a lambda is the last expression in its definition, unless the last expression is empty or an assignment, in which case the lambda returns the generic null ::.

:x has a lambda terminate and return x.

q)foo:{if[0>type x;:x]; x cross x}
q)foo 2 3
2 2
2 3
3 2
3 3
q)foo 3
3

Signalling and trapping errors

Signal will exit the lambda under evaluation and signal an error to the expression that invoked it.

q)goo:{if[0>type x;'`type]; x cross x}
q)goo 2 3
2 2
2 3
3 2
3 3
q)goo 3
'type
  [0]  goo 3
       ^

Trap and Trap At set traps to catch errors.

Control words

do

evaluate some expression/s some number of times

exit

terminate kdb+

if

evaluate some expression/s if some condition holds

while

evaluate some expression/s while some condition holds

Iteration

Control words are little used in practice for iteration. Iterators are more commonly used.

Iterators:
Maps – Case, Each, Each Left, Each Right, Each Parallel, Each Prior
Accumulators – Converge, Do, While, Scan, Over

Common errors

Control words are not functions, and return as a result only Identity.

A common error is forgetting to terminate with a semi-colon.

The result of if, do, and while is Identity, (::), which allows one mistakenly to write code such as a:if[1b;42]43 (instead use Cond), or a:0b;if[a;0N!42]a:1b – the sequence is not as intended!