Adverbs
Adverbs are primitive higher-order functions: they return derived functions, known as derivatives. They are much used for iteration.
q)+/[2 3 4] /reduce 2 3 4 with +
9
q)*/[2 3 4] /reduce 2 3 4 with *
24
Adverb syntax, .Q.fu (apply unique)
| form | adverb | semantics |
|---|---|---|
int'[x;y;…] |
case | select from [x;y;…] |
'[f;g][x;y;…] |
compose | compose f with g |
x f'y |
each-both | apply f between items of x and y |
x f\:y |
each-left | apply f between y and items of x |
x f/:y |
each-right | apply `f betweenxand items ofy` |
f':x |
each-parallel | apply f to items of x in parallel tasks |
f':x |
each-prior | apply f between successive pairs of items of x |
f/x |
converge | apply f to x until converges |
x f/y |
repeat | apply f to y, x times or while x |
x f/y |
over | reduce y with f |
f/[x;y;…] |
fold | reduce [x;y;…] with f |
f\x |
converge | apply f to x until converges |
x f\y |
iterate | apply f to y, x times or while x |
f\x |
scan | apply f/ to successive items of x |
Key: int: int vector; f: function; g: function; x: data; y: data.
' (case)¶
Pick successive items from multiple list arguments: the left argument of the adverb determines from which argument of the derivative each item is picked.
Syntax: d:x' (unary, postfix)
Derivative: d y (multivalent)
Where x is an integer vector and args are the arguments to the derivative, the derivative x' returns r such that
r_i is (args_{x_i})_i
Atom arguments in y are treated as infinitely-repeated values.
q)0 1 0'["abc";"xyz"]
"ayc"
q)e:`one`two`three`four`five
q)f:`un`deux`trois`quatre`cinq
q)g:`eins`zwei`drei`vier`funf
q)l:`English`French`German
q)l?`German`English`French`French`German
2 0 1 1 2
q)(l?`German`English`French`French`German)'[e;f;g]
`eins`two`trois`quatre`funf
q)/extra arguments don't signal a rank error
q)0 2 0'["abc";"xyz";"123";"789"]
"a2c"
q)0 1 0'["a";"xyz"] /atom "a" repeated as needed
"aya"
Case is useful for selecting between record fields according to a test on some other field.
Suppose we have lists h and o of home and office phone numbers, and a third list p indicating at which number the subject prefers to be called.
q)([]pref: p;home: h; office: o; call: (`home`office?p)'[h;o])
pref home office call
---------------------------------------------------------
home "(973)-902-8196" "(431)-158-8403" "(973)-902-8196"
office "(448)-242-6173" "(123)-993-9804" "(123)-993-9804"
office "(649)-678-6937" "(577)-671-6744" "(577)-671-6744"
home "(677)-200-5231" "(546)-864-5636" "(677)-200-5231"
home "(463)-653-5120" "(636)-437-2336" "(463)-653-5120"
' (compose)¶
Syntax: d:'[g;f] (binary, prefix)
Derivative: d[x;y;z;…] (same rank as f)
Where f is a multi-argument function and g is a unary function, the derivative f' has rank f and returns g f[x;y;z;…].
q)f:{[w;x;y;z]w+x+y+z}
q)g:{2*x}
q)d:('[g;f]) / The interpreter is finicky about :'
q)d[1;2;3;4] / g f[1;2;3;4]
20
Compose a list of functions
This can be extended with over to compose a list of functions.
q)g1:{10*x}
q)d1:('[;]) over (g1;g;f) / Use ('[;]) so the correct form is used
q)d1[1;2;3;4]
200

' (each-both)¶
Applies a function between corresponding items of the argument lists.
Syntax: d:f' (unary, postfix)
Derivative: x d y (binary, uniform)
Where f is a binary function, and x and y conform, the derivative f' applies f between corresponding items of x and y.
q)0 1 2 3 ,' 10 20 30 40
0 10
1 20
2 30
3 40
If either x or y is atomic, it is paired to every item in the other argument.
q)0 1 2 3 ,' 10
0 10
1 10
2 10
3 10

\: (each-left)¶
Applies a function between each item of the left argument and the right argument.
Syntax: d:f\: (unary, postfix)
Derivative: x d y(binary, uniform)
Where f is a binary function, the derivative f\: applies f between y and each item of x where
xis a listyis an atom or a list
q)(til 5),\:0 1
0 0 1
1 0 1
2 0 1
3 0 1
4 0 1

/: (each-right)¶
Applies a function between the left argument and each item of the right argument.
Syntax: d:f/: (unary, postfix)
Derivative: x d y (binary, uniform)
Where f is a binary function, the derivative f/: applies f between x and each item of y where
xis an atom or a listyis a list
q)(til 5),/:0 1
0 1 2 3 4 0
0 1 2 3 4 1
Left, right, cross
Each-left combined with each-right
q){}0N!(til 4),\:/: til 4
((0 0;1 0;2 0;3 0);(0 1;1 1;2 1;3 1);(0 2;1 2;2 2;3 2);(0 3;1 3;2 3;3 3))
resembles the result obtained by cross
q){}0N!cross[til 4;til 4]
(0 0;0 1;0 2;0 3;1 0;1 1;1 2;1 3;2 0;2 1;2 2;2 3;3 0;3 1;3 2;3 3)

': (each-parallel)¶
Each item of the argument list is assigned to a slave task, where the function is applied to each of its items.
Syntax: d:f': (unary, postfix)
Derivative: d x (unary, uniform)
Where f is a unary function, the derivative f': assigns the items of x to separate slave tasks, and in each task applies f to each item of the sublist.
$ q -s 2
KDB+ 3.4 2016.06.14 Copyright (C) 1993-2016 Kx Systems
m32/ 2()core 4096MB sjt mark.local 192.168.0.17 NONEXPIRE
q)\t ({sum exp x?1.0}' )2#1000000 / each
185
q)\t ({sum exp x?1.0}':)2#1000000 / peach
79
q)peach
k){x':y}
command-line options, parallel processing, peach
Projecting a unary function with apply
You can use apply . to project a binary or higher-rank function as a unary function of a list of its arguments. The projection can then be combined with an adverb (such as each-parallel or converge-iterate) that takes a unary function as its argument.
q)f2:{(0|x-1;x rotate y)} / binary fn, returns 2-list
q)f1:f2 . / unary fn of a 2-list
q)f1\[(4;"hello")] / converge-iterate
4 "hello"
3 "ohell"
2 "llohe"
1 "ohell"
0 "hello"
Note that for converge-repeat and converge-iterate, the function must return a list of the same length as its rank.

': (each-prior)¶
Applies a function between each item of a list and its preceding item.
Syntax: d:f': (unary, postfix)
Derivative: d y (unary, uniform)
Derivative: x d y (binary, uniform)
Where f is a binary function, the ambivalent derivative f': applies f between each item of y and x,-1_y.
In unary application of the derivative, x defaults to (1#0#y)0.
q)99,':til 4
0 99
1 0
2 1
3 2
q)(,':)til 4 / x defaults to 0N
0
1 0
2 1
3 2
q)"abc",':"xyz"
"xabc"
"yx"
"zy"
q)0 1-':2 5 9
2 1
3
4
q)0-':2 5 9
2 3 4
q)-':[2 5 9] /deltas
2 3 4
| form | example | note |
|---|---|---|
f':[y] |
-':[ 1 4 9 16] |
unary |
(f':)y |
(-':) 1 4 9 16 |
juxtaposition |
x f': y |
9-': 1 4 9 16 |
infix (binary) |
f':[x;y] |
-':[9; 1 4 9 16] |
prefix (binary) |
f':[x;]y |
-':[9;]1 4 9 16 |
projection |
/ (converge-repeat)¶
Applies a function either a specified number of times, or until the result converges.
Syntax: d:f/ (unary, postfix)
Derivative: d y (unary)
Derivative: x d y (binary)
Where f is a unary function, the derivative f/
-
(converge) applied unary applies
frepeatedly toyuntil either (1) two successive results agree within comparison tolerance or (2) the result matchesy. The latter will save you from some infinite cycles but not all.
The related form converge-iterate can be useful to see the intermediate results. (Setq)(not/) 1b 0b q)(not/) 42 /never returns\P 0to see the convergence of your original computation.) -
(repeat) applied binary where (a)
xis a positive int atom, returns the result ofxsuccessive applications offtoyf f f … f f y/first 10+2 numbers of Fibonacci sequence q)10{x,sum -2#x}/0 1 / derived binary applied infix 0 1 1 2 3 5 8 13 21 34 55 89 /first n+2 numbers of Fibonacci sequence q)fibonacci:{x,sum -2#x}/[;0 1] / projection of derived function q)fibonacci 10 0 1 1 2 3 5 8 13 21 34 55 89or where (b)
xis a function, returns the result whenxapplied to the result returns0b.q){x+x}/[{x<1000};2] /prefix: f/[g;y] 1024 q){x<1000}{x+x}/2 /infix: g f/y 1024

/ (over)¶
Map-reduce: applies a binary function between elements of the argument, working from left to right.
Syntax: d:f/ (unary, postfix)
Derivative: x d y (ambivalent, aggregate)
Where f is a binary function and y has count n
f/[y]f[f[…f[f[y0;y1];y2];…yn-2];yn-1]f/[x;y]f[f[…f[f[x;y0];y1];…yn-2];yn-1]
q)(+/)2 3 4 /unary
9
q)0+/2 3 4 /binary
9
q)-/[8 1 9 5 4]
-11
ambivalent derivatives, over operator.
/ (fold)¶
Over (map-reduce) for functions with more than two arguments.
Syntax: d:f/ (unary, postfix)
Derivative: d[x;y;z;…] (same rank as f)
Where f is a function with rank above 2 and y, z, etc. conform, the derivative f/ has the same rank as f. Example: for f of rank 3 and y and z of count n)
f/[x;y;z]f[f[… f[f[x;y0;z0];y1;z1]; … yn-2;zn-2];yn-1;zn-1]
q){x+y+z}/[1 5 6;2 22;3 33]
61 65 66
Fold and over
Over is fold as applied to a binary function.
\ (converge-iterate)¶
Syntax: d:f\ (unary, postfix)
Derivative: d y (unary)
Derivative: x d y (binary)
Where f is a unary function, the derivative f\
-
(converge) applied unary calls
fonyrepeatedly until a value matching theyor the last result is produced. The result isyfollowed by all the results except the last.q)(neg\)1 1 -1 q)(rotate[1]\)"abcd" "abcd" "bcda" "cdab" "dabc" q)({x*x}\)0.1 0.1 0.01 0.0001 1e-08 1e-16 1e-32 1e-64 1e-128 1e-256 0 q){x*x}\[0.1] 0.1 0.01 0.0001 1e-08 1e-16 1e-32 1e-64 1e-128 1e-256 0 -
(iterate) applied binary,
xcan be either an integer number of iterations or a while-condition that returns an int or boolean which can be applied to the result off.q)f:1+ q)f\[3;100] 100 101 102 103 q)f\[105>;100] 100 101 102 103 104 105 q)f\[105>sum@;84 20] 84 20 85 21 q)3 f\100 /applied infix 100 101 102 103
\ (scan)¶
Syntax: d:f\ (unary, postfix)
Derivative: d y (unary, uniform)
Derivative: x d y (binary, uniform)
Derivative: d[x;y;z;…] (uniform)
Where f is a binary function (or matrix – see below), the derivative f\ applies f/ to successive items of
x@/: {(1+x)#\:x} til count x.
Its result is a list of the same count, built up as follows:
r0 = x0
ri = f[ri-1;xi] for i > 0
Where f\ is applied
-
unary
q)(+\)til 10 0 1 3 6 10 15 21 28 36 45 q)+\[til 10] 0 1 3 6 10 15 21 28 36 45 -
binary,
xis used as the initial value.q)1+\1 2 3 2 4 7 q)+\[1;1 2 3] 2 4 7 -
>rank 2,
xis used as the initial value and other arguments are corresponding items from the lists.q){(x;y;z)}\[0;1 2 3;4 5 6] 0 1 4 0 1 4 2 5 (0 1 4;2;5) 3 6
Finite-state machine¶
Consider a matrix as both a binary function (of row- and column-indexes) and a finite-state machine. Such a matrix can be applied via scan and over:
initialstate transitionmatrix\input
initialstate transitionmatrix/input
q)m:(0 2;1 1;0 1)
q)0 m\1 0 1 1 0 1
2 0 2 1 1 1
q)0 m/1 0 1 1 0 1
1
Alternative syntax¶
As of V3.1 2013.07.07, scan has a built-in function for the following.
q){{z+y*x}\[x;y;z]}
{{z+y*x}\[x;y;z]}
q){x y\z} /alternative syntax using built-in function
{x y\z}
Note that for the built-in version it is for floats.
/ over adverb, over operator, scan operator, Tutorial: Shifts and scans
Derivatives¶
The semantics of a derivative – what it does – is determined by
- the rank of the adverb’s function argument/s
- how the derivative is applied
Some derivatives are ambivalent, and what they do depends on whether they are applied as unary or binary functions. Most binary derivatives can be applied infix, e.g. 2+/3 4 5. A named derivative, e.g. total:+/ retains its ambivalence, but cannot be applied infix.
q)+/[2;3 4 5] ~ 2+/3 4 5 /prefix or infix
1b
q)total:+/
q)total[3 4 5] /unary (not a projection)
12
q)total[2;3 4 5] /binary
14
q)2 total 3 4 5 /but not infix
'type
[0] 2 total 3 4 5
^
Projecting an ambivalent derivative
Applying a binary function to one argument projects it on that argument: treble:*[3]. Ambivalent derivatives behave differently.
q)+/[2 3 4] /applied unary
9
An ambivalent derivative can still be projected using the full form.
q)tenandsum:+/[10;]
q)tenandsum 2 3 4
19
