How to Control Execution

This page walks you through how to manage conditional logic and loops in the q language.

Vector operations in q let you apply the same operation to entire lists (or columns) of data in one go, rather than stepping through each element with loops or branching logic. This has two major benefits for new q users: simplicity and speed.

That said, q still supports the classic control flow of if, while, do, and the $ operator, so when your logic really does need step-by-step branching (for example, when each iteration depends on the previous one), you have the full set of tools available. But, whenever you think in whole columns instead of elements one at a time, you write cleaner, faster q code.

Overview of steps

The first three topics deal with conditions, while the last two cover different types of loops:

  1. Use if for simple branching
  2. Apply the ternary $ operator for inline conditions
  3. Leverage vector conditional ? for element-wise logic
  4. Implement fixed-count iteration with do
  5. Run condition-driven loops using while

Conditions

Let's start with conditions.

If

The if keyword executes one or more expressions only when a boolean condition is true (1b). Variables created inside the brackets remain in scope after execution.

In this example, a count of command-line arguments (.z.x) is used to print a statement on whether KDB-X has been started with any arguments:

q

Copy
q)if[not count .z.x;show"No command line args used"]
"No command line args used"

Rerunning with q -param paramval shows that the condition is no longer true and doesn’t print the statement when run.

Name scope is the same within the brackets as without them. In the following example, x created within the brackets is also accessible outside them. y is not created as its condition is not true.

q

Copy
q)if[1b;x:33;show"true"]
"true"
q)x
33
q)if[0b;y:33;show"true"]
q)y
'y
  [0]  y
       ^

The result returned is generic null.

q

Copy
q)r:if[1b;x:33;x:55]
q)r~(::)                  / compare result returned to null
1b

Conditional operator $

One of the uses of $ is conditional evaluation.

Three expressions

If we pass three parameters through $ (ternary overload), this provides conditional evaluation, like other languages' use of if-then-else. If the condition is true, the second parameter is executed and returned, otherwise the third parameter is executed and returned.

q

Copy
q)x:0
q)$[x=0;"true, x is zero";"false, x is not zero"]
"true, x is zero"
q)x:1
q)$[x=0;"true, x is zero";"false, x is not zero"]
"false, x is not zero"

To make the test for zero more efficient, reverse the second and third argument and remove the comparison in the condition.

q

Copy
q)x:0
q)$[x;"false, x is not zero";"true, x is zero"]
"true, x is zero"
q)x:1
q)$[x;"false, x is not zero";"true, x is zero"]
"false, x is not zero"

Name scope is the same within the brackets as without them. In this example, because the condition is true, y is created within the brackets and is now accessible outside them, but z isn't created as the condition was not false.

q

Copy
q)x:0
q)$[x=0;y:22;z:33]
22
q)y
22
q)z
'z
  [0]  z
       ^

Odd number of expressions

For brevity, flatten nested conditional expressions. Implement$[q;a;$[r;b;c]] by $[q;a;r;b;c]. Translate conditions with multiple branches by repeatedly expanding the final three expressions.

For example, rewrite $[q;a;$[r;b;$[s;c;d]]] as $[q;a;r;b;s;c;d].

q

Copy
$[q;a;  / if q, a
  r;b;  / else if r, b
  s;c;  / else if s, c
  d]    / else d

Even number of expressions

An even number of expressions returns either a result or the generic null.

q

Copy
q)$[1b;`true;1b;`foo]
`true
q)$[0b;`true;1b;`foo]
`foo
q)$[0b;`true;0b;`foo]           / return generic null, no conditions were true
q)$[0b;`true;0b;`foo]~(::)      / compare with generic null to confirm
1b

Vector conditional

Vector conditions refer to applying boolean tests across entire arrays (or vectors) of values in one operation, rather than checking each element with an explicit loop.

Let's say we pass 3 parameters through ? (ternary overload), where the first parameter is a boolean vector, which provides vector conditional evaluation. The second and third elements must be the same type and conform to the size of the conditional vector. Where an element is true (1b), the corresponding element of the second vector (or atom) is chosen, otherwise if false (0b) the third vector (or atom) entry is chosen.

q

Copy
q)?[111000b;1 2 3 4 5 6;10 20 30 40 50 60]
1 2 3 40 50 60
q)?[111000b;1 2 3 4 5 6;10]
1 2 3 10 10 10
q)?[111000b;1;10 20 30 40 50 60]
1 1 1 40 50 60
q)?[111000b;1;10]
1 1 1 10 10 10

The following code shows an error for a non-conforming parameter based on the length of the conditional vector (the length of conditional vector is 3, but the first vector provided has 6 elements):

q

Copy
q)?[111b;1 2 3 4 5 6;10]
'length
  [0]  ?[111b;1 2 3 4 5 6;10]
       ^

Loops

Now, let's discuss loops. Use the control words do and while if needed, but they are rarely required, so it's better to vectorize code your code instead.

Do

The do keyword repeats one or more expressions a given number of times, like so:

q

Copy
q)do[2;show "loop"]
"loop"
"loop"
q)x:0
q)do[2;x:x+1;show "loop ",string x]
"loop 1"
"loop 2"

Name scope is the same within the brackets as without them. As is demonstrated below, x created within the brackets is also accessible outside them.

q

Copy
q)do[2;x:33;show "loop"]
"loop"
"loop"
q)x
33

If you need do to rerun code a number of time for profiling, the system command \t can be used instead, which also allows code to be executed a set number of times.

The result returned directly from do is generic null:

q

Copy
q)r:do[2;x:33]
q)r~(::)              / compare result returned to null
1b

While

The while keyword repeats one or more expressions while a condition is not equal to false (0b).

q

Copy
q)f:5
q)while[f:f-1;show"loop",string f]
"loop4"
"loop3"
"loop2"
"loop1"

Name scope is the same within the brackets as without them. As is seen below, x created within the brackets is accessible outside them.

q

Copy
q)f:2
q)while[f:f-1;x:66;show"loop"]
"loop"
q)x
66

The result returned directly from while is generic null.

q

Copy
q)f:2
q)r:while[f:f-1;x:66]
q)r~(::)                   / compare result returned to null
1b

Summary

In this guide, you learned how to:

  • Apply branching with if and inline $
  • Execute vectorized logic using ?
  • Iterate fixed counts using do
  • Construct condition‑based loops with while

Next steps

  • Practice combining vector conditions with aggregation
  • Explore performance tuning using in‑memory table operations
  • Integrate these constructs into real‑world data processing scripts
  • Deep dive into advanced control words like .Q functions and error handling

Feel free to refer back as you build complex q workflows. Happy coding!