Core Concepts
Functions
Defining and applying functions, lambdas, projections, composition, and recursion.
Overview
A q function is written in curly braces and is a value like any other: you can assign it to a name, store it in a list or dictionary, or pass it to another function. This page covers how to define and call functions, what they return, how variables inside them work, and how to handle errors. The Terminology page explains the vocabulary (rank, projection, application) in more depth.
Defining and Calling a Function
A function written in braces is called a lambda. If it doesn't name its arguments, q gives it up to three implicit ones, x, y and z:
sq:{x*x}
sq 4 / 16
sq 1 2 3 / 1 4 9
{x+y}[2;3] / 5To name the arguments, list them in square brackets at the start of the body:
notional:{[px;qty] px*qty}
notional[185.2;100] / 18520fCall a function by putting its arguments in square brackets, separated by semicolons. A function of one argument can also be called by writing the argument after it with a space, as in sq 4.
A lambda can have at most 8 arguments. Defining one with more signals 'params. If you need more, pass a dictionary or a list instead.
Return Values
A function returns the value of its last expression:
f:{a:x*2; a+1}
f 5 / 11If the last expression ends with a semicolon, the function returns the generic null ::, which the q session doesn't display. That is the normal way to write a function that is only run for its side effects:
g:{a:x*2; a+1;}
(::)~g 5 / 1bTo return early, write : followed by the value:
h:{if[x<0; :0]; x*10}
h -3 / 0
h 4 / 40Multi-Line Functions
In a script, a function can be spread over several lines. Every line after the first must be indented, and the closing brace goes on an indented line of its own:
vwap:{[px;qty]
total:sum px*qty;
total % sum qty
}
vwap[185.2 186.0;100 300] / 185.8Conditionals
$[test; a; b] (Cond) returns a if the test is true, and b otherwise. With more pairs, it works like an if/else-if chain:
sign:{$[x>0;`pos;x<0;`neg;`zero]}
sign each -2 0 3 / `neg`zero`posif[test; ...] runs the statements after the test only when the test is true, and doesn't return a value.
Local and Global Variables
A variable assigned with : inside a function is local: it exists only while the function runs. To assign a global variable from inside a function, use :::
counter:0
bump:{counter::counter+1}
bump[]
bump[]
counter / 2A function can read global variables without doing anything special.
Projections
Calling a function with only some of its arguments doesn't fail. It returns a projection: a new function that waits for the missing arguments:
qty100:notional[;100] / px is still to be supplied
qty100 185.2 186.0 / 18520 18600fOperators can be projected too. 2* is a function that doubles its argument:
k:2*
k 5 / 10The Projections and Default Arguments practice sections show how projections are used to fix settings once and reuse a function many times. (q has no default argument values: a common pattern is to pass a null and replace it, as in n:5^n.)
Recursion
A function can call itself by name. Inside an anonymous lambda, .z.s refers to the function that is running:
{$[x<=1; 1; x*.z.s x-1]} 6 / 720In q, recursion is usually not the best tool. The same result is prd 1+til 6, which is shorter and faster.
Signalling and Catching Errors
' followed by a string or symbol signals an error, which stops the function:
checkQty:{if[x<=0; '"qty must be positive"]; x}@[f; arg; handler] (Trap) calls f with arg, and if f signals an error, calls handler with the error message instead:
@[checkQty; 100; {[e] "failed: ",e}] / 100
@[checkQty; -5; {[e] "failed: ",e}] / "failed: qty must be positive"For a function of several arguments, use .[f; (arg1; arg2); handler].
Functions as Values
Because functions are values, you can put them in lists and apply each one in turn:
(sum;max;avg) @\: 1 2 3 / 6 3 2f@\: applies each function on the left to the argument on the right. Iterators like this one are covered on the Iterators page.