Atomic functions¶
Many q functions iterate recursively through list or dictionary arguments down to items of some depth.
Where a function recurses to the atoms of an argument, it is atomic in that domain: typically, left-atomic, right-atomic; or simply atomic for all its arguments.
A function that recurses to strings is string-atomic.
Formal definition¶
Where f
is a function, and x
is a list of its arguments, .[f;x]~.[f';x]
.
q).[+;(2;(3 4;5))]
5 6
7
q).[+';(2;(3 4;5))] / the iterator is unnecessary
5 6
7
Application, projection, and indexing
By extension, for a unary function, f
is atomic if f[x]~f'[x]
.
q)neg (5 2; 3; -8 0 2)
-5 -2
-3
8 0 -2
q)neg each (5 2; 3; -8 0 2) / the iterator is unnecessary
-5 -2
-3
8 0 -2
Informal definition¶
A unary is atomic if it applies to both atoms and lists, and in the case of a list, applies independently to every atom in the list. For example, the unary neg
is atomic. A result of neg
is just like its argument, except that each atom in an argument is replaced by its negation.
q)neg 3 4 5
-3 -4 -5
q)neg (5 2; 3; -8 0 2)
-5 -2
-3
8 0 -2
neg
applies to a list by applying independently to every item. Accessing the i
th item of a list x
is denoted by x[i]
, and therefore the rule for how neg
applies to a list x
is that the i
th item of neg x
, which is (neg x)[i]
, is neg
applied to the i
th item.
neg
can be defined recursively for lists in terms of its definition for atoms. To do so we need two language constructs.
- Any function
f
can be applied independently to the items of a list by modifying the function with the Each iterator, as inf'
. - The function
{0>type x}
has the value 1 whenx
is an atom, and 0 whenx
is a list.
Using these constructs, neg
can be defined as follows:
neg:{$[0>type x; 0-x; neg'[x]]}
That is, if x
is an atom then neg x
is 0-x
, and otherwise neg
is applied independently to every item of the list x
. One can see from this definition that neg
and neg'
are identical. In general, this is the definition of atomic: a function f
of any number of arguments is atomic if f
is identical to f'
.
A binary f
is atomic if the following rules apply (these follow from the general definition that was given just above, or can be taken on their own merit):
f[x;y]
is defined for atomsx
andy
- for an atom
x
and a listy
, the resultf[x;y]
is a list whose ith item isf[x;y[i]]
- for a list
x
and an atomy
, the resultf[x;y]
is a list whose ith item isf[x[i];y]
- for lists
x
andy
, the resultf[x;y]
is a list whose ith item isf[x[i];y[i]]
For example, the operator Add is atomic.
q)2 + 3 q)2 6 + 3
5 5 9
q)2 + 3 -8 q)2 6 + 3 -8
5 -6 5 -2
q)(2; 3 4) + ((5 6; 7 8 9); (10; 11 12))
7 8 9 10 11
13 15 16
In the last example both arguments have count 2. The first item of the left argument, 2
, is added to the first item of the right argument, (5 6; 7 8 9)
, while the second argument of the left argument, 3 4
, is added to the second argument of the right argument, (10; 11 12)
. When adding the first items of the two lists, the atom 2
is added to every atom in (5 6; 7 8 9)
to give (7 8; 9 10 11)
, and when adding the second items, 3
is added to 10
to give 13
, and 4
is added to both atoms of 11 12
to give 15 16
.
Add can be defined recursively in terms of Add for atoms as follows:
q)Add:{$[(0>type x) & 0>type y; x + y; Add'[x;y]]}
Length and type¶
The arguments of an atomic function must be conformable.
q)1 2 3 + 4 5
'length
[0] 1 2 3 + 4 5
^
Type errors can arise at depth.
q)1 2 3 + (4;"a";5)
'type
[0] 1 2 3 + (4;"a";5)
^
Rank¶
Atomic functions are not restricted to ranks 1 and 2. For example, the ternary {x+y xexp z}
(“x plus y to the power z”) is atomic.
Left- and right-atomic¶
A function can be atomic relative to some of its arguments but not all. For example, the Index At operator @[x;y]
is an atomic function of its right argument but not its left, and is said to be right-atomic, or atomic in its second argument. That is, for every left argument x
the projected unary function x@
is atomic. This primitive function, like x[y]
, selects items from x
according to the atoms in y
, and the result is structurally like y
, except that every atom in y
is replaced by the item of x
that it selects.
q)2 4 -23 8 7 @ (0 4 ; 2)
2 7
-23
Index 0 selects 2; index 4 selects 7; and index 2 selects -23.
String-atomic¶
Q does not have a string datatype. What we call strings are char vectors.
Some functions that apply to strings recurse until they find either strings or char atoms. They are string-atomic.
q)upper ("quick";("brown";"fox");"x")
"QUICK"
("BROWN";"FOX")
"X"
Q for Mortals §6.6 Atomic Functions