The Each iterators
Functions derived by Each and its variants work independently on their argument items.
Apart from Case, the map iterators are variations of Each '
.
Each
The Each iterator applied to a function f
derives a function f'
of the same rank as f
.
Where f
has rank \(N\), you can apply f'
with bracket syntax to an argument list of \(N\) conforming lists or dictionaries.
q)/ rank 1
q)til'[2 0 5]
0 1
`long$()
0 1 2 3 4
f'
iterates f
over corresponding items from the list arguments.
q)/ rank 2
q)?'[("abc";"defg";"qrs";"tuvw");"best"]
1 1 2 0
("abc"?"b";"defg"?"e";"qrs"?"s";"tuvw"?"t")
.
q)/ rank 3
q){x~y rotate asc z}'[("abc";"fed");0 1;("cab";"def")]
10b
Unary functions
Where f
is unary, so too is f'
.
But you can’t apply a unary f'
with prefix syntax.
Why not? Because…
All derived functions have infix syntax regardless of their rank.
Why is that? Don’t know. Brute fact. Mysteries of the q parser.
So you cannot apply unary f'
with prefix syntax (e.g. e.g. count'x
– wrong!) because the parser sees count'
has infix syntax and looks for a left argument that count'
does not and cannot have.
You can however parenthesise the derived function, which captures it as a noun (count')
, and you can apply a noun with prefix syntax.
So (count')x
works.
For the same reason you cannot make count'
the left argument of Apply At @
with infix syntax (i.e. count'@x
– wrong!), but you can use it as an item of its argument list.
q)@[count';("quick";"brown";"fox")]
5 5 3
each
keyword (see below), and that is preferred style.
q)count each ("quick";"brown";"fox")
5 5 3
Summary:
f'[x] / works: bracket syntax
f'x / ERROR: prefix syntax
(f')x / works: (noun) & prefix syntax
f each x / preferred: keyword
Binary functions
Where f
is binary, good q style applies it with infix syntax as x f'y
.
Eachboth
Because
 the
each
keyword is good style for unary functions  most q primitives are unary or binary
f'
has infix syntax, allowingx f'y
the Each iterator has sometimes been called eachboth. This wrongly suggests it is limited to binary functions, which is not true.
Summary:
f'[x;y] / works: bracket syntax
x f'y / preferred: infix sytax
Higherrank functions
Where f
has rank 3–8, f'
will iterate it through list arguments.
Use bracket syntax f'[x;y;z]
.
q)
q)ssr'[("cow";"sheep";"cat";"dog");("c";"ee";"c";"g");"sobe"]
"sow"
"shop"
"bat"
"doe"
Summary:
f'[x;y;z;..]
Each Left and Each Right
The Each Left \:
and Each Right /:
iterators are syntactic sugar for the common iterations of binary functions in which either x
or y
is the same for each iteration.
q)"abc",\:"def" / Each Left
"adef"
"bdef"
"cdef"
q)"abc",/:"def" / Each Right
"abcd"
"abce"
"abcf"
p:,["abc"] / projection
p'["def"] / bracket syntax
p each "def" / keyword
(p') "def" / (noun) prefix
Each Parallel
Where f
is a unary (or variadic) function, Each Parallel f':
iterates f
as a unary through the items of a list or dictionary, dividing the work between secondary tasks.
Where no secondary tasks are configured, Each Parallel is the same as Each.
Multithreading primitives
The multithreading primitives feature introduced in kdb+ v4.0 makes Each Parallel redundant for q primitives.
Preferred style is to use the peach
keyword.
Summary:
f':[x] / works: bracket syntax
f peach x / preferred: keyword
Each Prior
Where f
is a binary function (or rank2 list or dictionary)
f':[y] <==> y f' I , 1_y
x f':y <==> y f' enlist[x] , 1_y
f
is one of these six operators:
f: +  * % & ~
I: 0 0 1 1 0W (::)
(apart from Match^{1}, rightidentity elements for f
)
otherwise I
is first y 1
.
Each Prior and vectors
Apart from the six operators, for vector y
f':[y] <==> y f'prev y <==> (f) prior y
q)mod':[3 4 5]
0N 1 1
q)3 4 5 mod'prev 3 4 5
0N 1 1
q)(mod) prior 3 4 5
0N 1 1
q)prev"abc"
" ab"
q),':["abc"] / Join Each Prior
"a "
"ba"
"cb"
q)show A:4 5#.Q.a
"abcde"
"fghij"
"klmno"
"pqrst"
q)2 1 3 A'prev 2 1 3
" hq"
q)A':[2 1 3] / A Each Prior
" hq"
Nonvector lists
If the first item of a general list is an atom, the derived function can be applied, provided adjacent items conform.
q)q <' prev q:(3;4;99 100;01b;6;50 51 51;7;8)
0b
0b
00b
11b
00b
000b
111b
0b
q)<':[q] ~ q <' prev q
1b
y 0
is not an atom, prev y
would return a leading empty list, but for an operator Each Prior substitutes I
as above.
q)q < prev q:(99 100;3;4;5)
'length
[0] q < prev q:(99 100;3;4;5)
^
q)prev q
`long$()
99 100
3
4
q)first q 1
0N
q)<':[q] / first item is 99 100<0N
00b
11b
0b
0b
First items must have nonzero data types.
If 0=type first y
, then I
will be ()
and f':[y]
will signal a length error.
Keywords
Four keywords correspond to commonly used functions derived by Each Prior.
deltas ':
differ <>':
prev ':
ratios %':
The keywords are variadic, but use them only as unaries.
These keywords are wrappers for the derived functions and so are also variadic.
q)a
2 1 3 4 1 2 1 5 4
q)deltas a / unary
2 3 4 7 5 3 1 6 9
q)deltas[1000;a] / binary
1002 3 4 7 5 3 1 6 9
q)deltas a / unary
2 3 4 7 5 3 1 6 9
q)1000':a / binary
1002 3 4 7 5 3 1 6 9
Iterator keywords
Keywords each
, peach
, and prior
are not iterators but binary keywords with infix syntax.
Their left arguments are functions.
You can ensure a function is parsed as the argument of a keyword (rather than evaluated) by parenthesising it to make a noun.
q)M:3 4#til 12
q)(+/) each M
6 22 38
(+/)
has noun syntax and the derived function +/
is the left argument of each
.
Parentheses are unnecessary where a function’s rank is unambiguous.
Above, +/
is variadic; and parentheses stop the parser looking for its arguments.
Below, count
and sum
are unambiguously unary, and need no parentheses.
q)sum each M
6 22 38
q)count each M
4 4 4
The keywords each
and peach
take unary left arguments; prior
a binary.
q)(+)prior til 5
0 1 3 5 7
q){x+y} prior til 5
0N 1 3 5 7
Above, the lambda is unambiguously binary and is parsed as the left argument to prior
.
But +
has a (deprecated) unary form and needs parentheses around it.
Except for lambdas and unary keywords, parenthesise all left arguments of each
, peach
and prior
.
So, count each x
but (+) prior x
.
Exercises
No peeking.
Attempt each exercise before looking at its answer.
The exercises clarify your thinking. Reading answers does not.

Simplify
3 4+'5 6
.Answer
The Add operator has atomic iteration so the Each operator is redundant.
3 4+5 6

Simplify
("quick";"brown";"fox")?\:"o"
.Answer
Scalar extension makes the
"o"
atom equivalent here to"ooo"
, so Each Left can be replaced with Each.("quick";"brown";"fox")?'"o"

Explain why
count each
andcount'
have different types.q)type each(count';count each) 106 104h
Answer
Functions derived by Each, such as
count'
have type 106.In contrast,
count each
projectseach
ontocount
and is therefore equivalent toeach[count;]
. As a projection, it has type 104. 
Simplify:
(,["https://";])each urls
Answer
Above, Join
,
is projected on"https://"
and the projection forms the left argument ofeach
. It can be simplified by omitting both the parentheses and the semicolon, but with no increase in clarity.Better: use Each Right.,["https://"] each urls
"https://",/:urls

Explain why the expressions below have different results.
q)(+) prior til 5 0 1 3 5 7 q){x+y} prior til 5 0N 1 3 5 7
Answer
The lambda adds 0 (i.e.
til[5]@0
) totil[5]@1
, which is the null0N
.The operator is one of the list of special cases. It adds
til[5]@0
to itself. 
Below, use
KEY
to extractsecret
fromcipher
.q)secret:"mypassword" q)KEY:neg[1+n]?N:2*n:count secret q)show cipher:./[N cut(N*N)?.Q.a;1_,':[KEY];:; secret] "ipstdnynogqxjxwboipo" "rccwdhdgamjcsweyrudu" "rzfggdyjamjsomuypcqr" "awijrkjyzavfgkebpjlg" "pnrppyqrpveeyzjlexbx" "ailiexwmmrhlmfuijxzu" "khaqghfgelmfrilvibfm" "pntmethjkvfggvbpcyfw" "iunqbvillxfiqkoehrbw" "rxwwsesustqqrlznekcs" "ubfndhkcmhjuxlwnadax" "hkzhrgxvujbkodvgtlso" "rwhtrzhvlwfxrfyxfdue" "tpuhqfyiquhpzgysrlcz" "nbodbwrtpdnmimuubhdt" "bofzemgnzqtmkbcptgbs" "dgmvgkkjzajugcleamao" "pcwtdgepaoggdusfycuh" "kmxaeockvwyqtdcphlnm" "xvwsqmuokcapqhtlpghn"
Answer
List
cipher
is a matrix randomly filled with letters into whichsecret
is inserted at indexes generated fromKEY
.To extract
secret
fromcipher
regenerate the indices fromKEY
with Index Each Right./:
q)cipher ./: 1_,':[KEY] "mypassword"

Lesser (
&
) is a special case when Each Prior is applied to it. Should Greater (
) also be a special case? Justify your answer.Answer
Because
1b ~ 00N
the specialcase model and the definitionx'prev x
of Greater Each Prior both return the same result. So, either Yes
 Greater should join Lesser and other comparison operators in the list of special cases.
 No

Greater Each Prior conforms to the definition pattern and is not a special case.
':[x] <==> x  prev x

Let
M:4 5#20?100
. Amendsd:{sum xy}
so thatsd prior M
returns a result.Answer
sd prior M
signals a length error withsd:{sum xy}
becausefirst prev M
is`long$()
.sd:{sum x$[count y;y;0]}
allowssd prior M
to evaluate.

This special treatment for Match ensures that the first item of the result of
differ x
is1b
– unlessx[0]
is the general null! ↩