Skip to content

Style

Fluency with the syntax of q promotes clarity of expression and thought, and reduces maintenance costs.

Apply a binary between two values

The Over iterator can be used to ‘map reduce’ a list using a binary. Where a list has just two items it can also be used to apply a binary to them. This is a form convenient in ancestor vector languages, redundant in q.

Where a list is known to have two items, use Apply, which tells your reader to expect a 2-list.

For example, not this:

q)x:2 3
q){x*5+y} over x
16
q)(xexp) over x
8f
q)(*) over x
6

but this:

q){x*5+y} . x           / lambda
16
q)(xexp) . x            / keyword
8f
q)(*) . x               / operator
6

Example – vector product:

q)x:2 8 5 6 3 1 7 7 10 4
q)y:6 9 1 1 6 7 1 4 1 5
q)(-) over prd each(1 neg\1 -1)rotate''2 2#(x;y)
4 28 46 -27 -41 39 45 3 -19 -58

Above, the Subtract Over reduction is an unnecessarily general way to get the difference of two lists.

q)prd each(1 neg\1 -1)rotate''2 2#(x;y)                 / a 2-list
40 30 54 3  1  42 49 10 16 2
36 2  8  30 42 3  4  7  35 60
q)(-). prd each(1 neg\1 -1)rotate''2 2#(x;y)            / Apply, not Over
4 28 46 -27 -41 39 45 3 -19 -58

Example – connection matrix from node matrix:

q)show x:(0 0 2 1 1;2 1 3 2 3)          / node matrix
0 0 2 1 1
2 1 3 2 3
q)x=/:tc distinct raze x                / where is x equal to each of it
11000b 00000b
00011b 01000b
00100b 10010b
00000b 00101b
q)(-/)each x=/:tc distinct raze x       / connection matrix
1  1  0  0  0
0  -1 0  1  1
-1 0  1  -1 0
0  0  -1 0  -1

The last expression above returns the difference between two matrixes. Flipping them makes this clearer.

q)shape x=/:tc distinct raze x
4 2 5
q)shape flip x=/:tc distinct raze x     / 2-list
2 4 5
q)(-). flip x=/:tc distinct raze x      / single subtraction
1  1  0  0  0
0  -1 0  1  1
-1 0  1  -1 0
0  0  -1 0  -1

Coefficients of exponential fit of points (x,y)

Project to avoid parens

Improve the reading flow of expressions by using projections to avoid parentheses.

q)y:1900 1901 1904 1999 2000 2100               / years
q){(sum 0=x mod\:4 100 400)mod 2}each y         / leap years
0 0 1 0 1 0
q){mod[;2] sum 0=x mod\:4 100 400}each y
0 0 1 0 1 0

Compose to avoid multiple iterators

Compose a unary function with another function into a single iterable object. Composition makes peach more efficient.

rank of g not this nor this but this
1 f each g each x {f g x}each x ('[f;g])each x
2 f each x g'y x{f g[x;y]}'y x('[f;g])'y
3 f each g'[x;y;z] {f g[x;y;z]}'[x;y;z] ('[f;g])'[x;y;z]

Extend Compose with Over to compose multiple unary functions with another function.

q)foo:(('[;])over (d;e;f;g))
q)foo each x                    / unary g
..
q)x foo'y                       / binary g
..
q)foo'[x;y;z]                   / ternary g
..
rank of g not this but this
1 {d e f g x}each x foo each x
2 x{d e f g[x;y]}'y x foo'y
3 {d e f g[x;y;x]}'[x;yx;z] foo'[x;y;z]

Operators and their projections can be composed by juxtaposition.

q)x:-100 2 3 4 -100 6 7 8 9 -100
q)(x;0 (0|+)\x)                     / running sums of parts
-100 2 3 4 -100 6 7  8  9  -100
0    2 5 9 0    6 13 21 30 0