Send Feedback
Skip to content

How to Work with Functions

This page explains how to define, call, and manage functions in q, including arguments, scoping, projections, and return behavior.

A function in q is a reusable block of logic, a sequence of expressions that execute in order. Functions can take zero or more inputs and return an output.

Overview

Define a function

Define a function in q using lambda notation, which consists of:

  • Curly braces {} for the function body
  • Optional argument list (up to 8 named parameters) inside square brackets []
  • One or more expressions separated by semicolons ;

For example, let's define a lambda named plus that adds two arguments:

q)plus:{[x;y] x + y}

In q, a lambda refers to any function defined using this notation, whether anonymous or assigned to a name.

Treat functions as data

Functions in q behave like other data types (integers, symbols, etc). Use type to confirm a function’s type:

q)func:{[x;y]x+y}
q)type func
100h

A return value of 100h indicates a lambda function. You can:

  • Pass functions between processes via IPC
  • Use them as arguments or return values in other functions
  • Store them in lists or dictionaries

Functions that operate on or return other functions are called higher-order functions.

Understand function rank

The rank (or valence) of a function is the number of arguments it accepts.

You may define functions with up to 8 arguments. Using more raises a params error:

q)f:{[a;b;c;d;e;f;g;h]a*b-c+d*e-f*g+h}
q)f:{[a;b;c;d;e;f;g;h;i]a*b-c+d*e-f*g+h+i}
'params

Functions are often described by their rank:

  • Niladic: accepts no arguments (rank 0)
  • Monadic/Unary: accepts one argument (rank 1)
  • Dyadic/Binary: accepts two arguments (rank 2)

Functions can inspect the type or length of their arguments at runtime using type or count.

This allows them to branch logic accordingly; for example, built-ins like load and hopen behave differently depending on input type.

Call functions with arguments or projections

Call a function in q using function application syntax: function name followed by arguments inside square brackets [], separated by semicolons ;.

q)func:{[x;y]x+y}
q)func[22;33]
55

Call functions without arguments

If the function doesn’t require arguments, include empty brackets:

q)func:{show "func called";}
q)func[]
"func called"

Evaluate expressions in arguments

q evaluates expressions inside argument positions before passing them:

q)func:{[x;y]x*y}
q)func[2+8;2]
20

Handle rank errors

Calling a function with too many arguments results in a rank error:

q)func:{[x;y]x*y}
q)func[22;33;231;123]
'rank

Call functions by name or symbol

You can call a function directly using its variable name or indirectly by symbol:

q)func:{[x;y]x+y}
q)func[10;2]
12

q)`func[10;2]
12

q)a:`func
q)a[10;2]
12

Use prefix notation

Functions that take only one argument also support prefix notation, omitting brackets:

q)f:{[x]x*x}
q)f[22]
484
q)f 22                  / prefix notation
484

Calling a function with fewer arguments than declared results in a projection.

Use anonymous functions

Anonymous functions are useful for one-off operations or dynamic evaluation.

Define and call inline

q){[x]x*x} 2
4

Apply to a list

Use an anonymous function with each to apply logic to every item in a list. In the example below, we convert a list of server addresses into connection handles. The anonymous function first transforms each string into a symbolic handle using hsym, then opens a connection using hopen:

q)machines:("qa-machine1:1234";"qa-machine2:5234";"qa-machine3:2234")
q)h:{[x]hopen hsym `$x} each machines
q)h
6 7 8i

Store functions in collections

Store anonymous functions in lists, dictionaries, or tables to support dynamic dispatch.

Work with function arguments

Use implicit arguments

Define a function without naming its arguments. q automatically provides up to three implicit arguments:

  • x
  • y
  • z
q)f:{22+x+x}    / implicit single argument x
q)f[2]
26
q)f:{y-x}       / implicit arguments x and y
q)f[2;10]
8
q)f:{z*z}       / implicit argument z
q)f[2;3;4]
16

Anonymous functions also benefit from implicit arguments.

q)h:{hopen hsym `$x} each ("qa-machine1:1234";"qa-machine2:5234")   / anonymous function with an implicit single argument x

A function with named arguments is called signed. Without named arguments, it is unsigned.

Apply argument type checking

Define argument types inside the function signature using a single-character type code after a colon (:). For example, use `j to restrict a parameter to type long.

q)f:{[someLong:`j] 2*someLong}
q)f[2]
4
q)f[2.2]
'type
  [1]  f:{[someLong:`j] 2*someLong}  

This enforces type safety and improves code robustness.

Manage local and global variables

Use local and global variables to control scope and data visibility in q functions. Understand how variable assignment and access behave depending on the context.

Define local variables

Create local variables inside a function using :. Local variables:

  • Exist only during function execution
  • Remain invisible outside the function scope
  • Cannot be used in call-by-name functions
  • Stay hidden from local functions nested inside the same scope

Local assignments don't affect external values:

q)v:22
q)f:{[x]x:100}
q)f[v]
100
q)v
22

Modifying elements of a passed-in vector also has no lasting effect:

q)v:1 2 3
q)f:{[x]x[0]:100}
q)f[v]
q)v
1 2 3

Assignments with : apply locally and don't overwrite global variables:

q)a:22                         / global 'a'
q)f:{[x]a:33;b:44;a+b+x}       / function creates local variables 'a' and 'b', local 'a' takes precedence
q)f[1]
78
q)a                            / global 'a' remains unchanged
22
q)b                            / no global 'b' defined, error occurs
'b

Resolve references to names not defined locally from the current namespace:

q)a:42           / assigned in root
q)f:{a+x}
q)f 1            / f reads a in root
43
q){a:1000;f x}1  / f reads a in root
43

Avoid assigning locals conditionally - local variables initialize to empty list () and conditional paths may leave them undefined.

q)t:([]0 1)
q){select from t}[]                       / global t
x
-
0
1
q){if[x;t:([]`a`b)];select from t} 1b     / local t
x
-
a
b
q) {if[x;t:([]`a`b)];select from t} 0b     / local t is ()
'type
  [4]  {if[x;t:([]`a`b)];select from t}
                         ^      

Use global variables

Access

Resolve names not defined locally from the current namespace:

q)v:10
q)f:{[x]x+v}
q)f[2]
12

Resolution depends on the active namespace:

q)v:10
q)\d .foo
{[x]x+v}[2] / errors as .foo.v doesn't exist
'd
.foo)v:20
{[x]x+v}[2] / resolves to .foo.v
22
\d .
q){[x]x+v}[2] / resolves to v in top namespace
12

Assign

Assign global values using ::. These assignments persist beyond the function call:

q)v:0
q)f:{[x]v::x;x+x}
q)f[1]
2
q)v
1
q)f[2]
4
q)v
2

Avoid confusion when assigning to globals with the same name as locals. :: still binds to the local scope if already defined:

q)v:0
q)f:{[x]v:0;v::x;x+x}
q)f[1]
2
q)v
0

Use set to reliably write to global variables:

q)v:0
q)f:{[x]v:0;`v set x;x+x}
q)f[1]
2
q)v
1

Use get to access global variables by name:

q)x:22
q)f:{[x]show x;}           / prints local variable x
q)f 101
101
q)f:{[x]show get `x;}      / prints global variable x
q)f 101
22   

Pass variables by reference

Avoid copying large datasets by passing variable names to functions and modifying them using get and set. By default, q passes arguments by value. When working with large vectors or tables, use symbolic references instead:

q)a:10 20 30 40 50
q)f:{[x]show get x;x set 10 20 30;}
q)f[`a]                  / call function, passing variable name
10 20 30 40 50
q)a                      / function used set to change variable
10 20 30     

Return values and exit behavior

Control what your function returns, whether it's a result, an early exit, or no value at all.

Return the result of the last expression

If the final expression does not end with a semicolon, the function returns its value:

q)f{[x]x+x}
q)f[2]
4

Return early with an empty assignment

To return early, use an empty assignment (: followed by a value):

q)c:0
q)f:{a:6;b:7;:a*b;c::98}
q)f 0
42
q)c
0

Create a void function

Use a semicolon on the last line to suppress the return value. The function returns the generic null:

q)f:{2*x;}      / last statement is empty
q)f 10          / no result shown
q)(::)~f 10     / matches generic null
1b

Signal an error or abort

To abort evaluation immediately, use signal, which is ' with a value to its right:

q)c:0
q)g:{a:6;b:7;'`TheEnd;c::98}
q)g 0
'TheEnd
  [0]  g 0
       ^

Example: Check argument type before proceeding. Use early return or error signaling to validate input:

q)f:{if[7h<>type x;'"type"]count x}
q)f[33 22]
2
q)f[22.4]
'type

Use projections for partial function application

When you call a function with fewer arguments than its defined rank, q returns a projection—a partially applied function. This projection “locks in” the arguments you’ve supplied and waits for the rest.

Other languages may refer to this concept as currying.

Create a projection by omitting arguments

Call a function with fewer arguments than it requires to return a projection (a partially applied function):

q)add:{[x;y]x+y}
q)add42:add[42;]           / create a projection with the first parameter value fixed to '42'
q)add42[2]                 / execute the original function with parameters 42 and 2
44
q)add42[4]                 / execute the original function with parameters 42 and 4
46

Create projections in stages

Chain projections by supplying arguments over multiple stages:

q)addm:{[x;y;z]x+y+z}    
q)addm[2;;3][6]            / projection with 1st and last parameter, then executed providing the remaining 2nd parameter
11
q)addm[2;;][2;][6]         / projection with the 1st parameter (2nd/3rd remaining), then create a new projection with only the first of the remaining 2 parameters needed, then execute the function when last parameter provided 
10  

Preserve logic in projections

The function logic is frozen at the time you create the projection. Redefining the original function later does not affect previously created projections:

q)f:{x*y}
q)g:f[3;]   / triple
q)g 5
15
q)f:{x%y}
q)g 5      / still triple
15

Use full-length argument lists

Use placeholders (;) for omitted arguments to clearly show the projection:

q)foo:{x+y+z}
q)goo:foo[2]    / discouraged
q)goo:foo[2;;]  / recommended

Check the type of projections

As with functions, projections have their own data type. Use type to inspect it:

q)f:{[x;y]x+y}
q)type f
100h
q)type f[1;]
104h

Projections let you fix arguments and reuse or defer execution until more input is provided.

Summary

In this guide, you learned how to:

  • Define functions using lambda notation
  • Treat functions as data and pass them around
  • Understand function rank and argument handling
  • Call functions with arguments, projections, and prefix notation
  • Use anonymous functions and apply them to lists
  • Manage local and global variables, including pass-by-reference
  • Control return values, early exits, and error signaling
  • Use projections for partial function application and currying

Refer back to this guide as you build and manage functions in q for robust, reusable code.