Core Concepts
Iterators
Each, each-both, each-left, each-right, scan, over — higher-order iteration in q.
Overview
Iterators (', /, \, \:, /:, ':) are the idiomatic way to apply functions across lists and dictionaries in q. An iterator takes a function and returns a new, derived function that applies the original in a particular pattern.
A note on names: iterators are sometimes called adverbs in older q/k documentation and community discussion — likewise verb maps to operator/keyword, and valence maps to rank. The Terminology page uses the modern names throughout; it's worth recognising "adverb", "verb", and "valence" as the same concepts if you encounter them elsewhere.
Maps vs Accumulators
Iterators fall into two groups:
- Maps distribute the application of a function across the items of a list or dictionary, and are implicitly parallel. This group includes Each (
'), Each Prior, Each Parallel (peach), Each Left (\:), Each Right (/:), and Case — some of these share glyphs (e.g.':is both Each Prior and Each Parallel, depending on context). - Accumulators — Over (
/) and Scan (\) — apply a function successively: first to the whole argument, then to the result of that, and so on. With a binary function, these correspond to map-reduce and fold in other languages.
This page covers Each-Both, Converge, and Over and Scan with a seed. The practice sections cover Each, Each Left, Each Right, Over, Scan and amend.
Each-Both
Each-both (') applied to a binary function applies that function to corresponding pairs of items from two lists. For atomic functions like +, this looks identical to plain application:
+'[1 2;10 20] / 11 22 (same as 1 2 + 10 20)Each-both is more meaningful for functions that aren't atomic. The join operator , normally concatenates two lists end to end — but with ,', it joins them pairwise, item by item:
(1 2;3 4),(10 20;30 40) / plain join -> (1 2;3 4;10 20;30 40) four rows
(1 2;3 4),'(10 20;30 40) / each-both -> (1 2 10 20;3 4 30 40) two rowsConverge
Converge is a special form of the Over (/) and Scan (\) iterators: when no iteration count or stopping condition is given, the function is applied repeatedly until the result stops changing.
raze removes one level of nesting from a list:
nested: (1;(2;(3;4));5)
raze nested
/ 1
/ 2
/ 3 4
/ 5Using Converge (raze/), raze is applied repeatedly until the result is fully flat:
raze/[nested]
/ 1 2 3 4 5Converge is uncommon in mainstream languages but is a powerful tool in q, especially for recursive or arbitrarily nested data structures.
Do and While are two close relatives — they use the same Over/Scan syntax but control when to stop differently:
- Do (
n f/ x) — applyfexactlyntimes. Use Scan (\) to see every intermediate step, or Over (/) for the final result only:
3 {x+1}\ 5 / 5 6 7 8 (start, then 3 steps)
3 {x+1}/ 5 / 8 (final result only)- While (
t f/ x) — keep applyingfuntil the test functiontreturns false. Again,\for all steps,/for just the end:
{x<100} {x*2}\ 1 / 1 2 4 8 16 32 64 128
{x<100} {x*2}/ 1 / 128Converge applies to any unary function, not just raze. A classic example is summing a matrix — expressions like these are shorter and usually faster than an explicit loop:
m: (1 2 3;4 5 6;7 8 9)
+/[m] / sum the columns -> 12 15 18
+/'[m] / sum each row -> 6 15 24
+//[m] / sum everything -> 45 (Converge: +/ applied repeatedly until the result stops changing)Seeded Over & Scan
Both Over (/) and Scan (\) accept an optional seed (initial value) as a left argument — this is the binary form of the derived function:
+\[1 2 3] / unary -> 1 3 6 (running totals)
+\[1; 1 2 3] / binary -> 2 4 7 (seed 1, then running totals)
1 +\ 1 2 3 / same as above, written infix -> 2 4 7The same applies to / (e.g. +/[100;1 2 3 4] → 110). See the Terminology page's "Derived Function" section for a syntax gotcha around writing these forms without brackets or parentheses.