oK aims to be an implementation of k6, the still-evolving bleeding edge version of the K programming language. This manual will serve as a short but more comprehensive reference than the official k6 reference card. Since both oK and k6 are unfinished, this document will attempt to describe oK's current behavior and will be updated as semantics are brought in line with k6.
K may look daunting at first, but the syntax of the language is very simple and regular. Programs consist of a series of expressions which are made up of nouns, verbs and adverbs. Nouns can be simple atomic types like numbers, characters or symbols or they can be the compound datatypes lists, dictionaries or functions. In general, ()
are for grouping subexpressions or forming lists, []
are used for creating dictionaries, indexing into a list or applying arguments to a function, {}
are used for delimiting functions and newlines always behave identically to semicolons (;
). The colon (:
) has several possible meanings in different contexts, but most frequently behaves as an assignment operator binding the result of a right-hand expression to a name:
quux: 23+9
-
Numbers are composed of digits and can optionally have a leading negative sign or decimal part.
-
Characters are enclosed in double quotes (") and can make use of the escape sequences
\n
,\t
,\"
or\\
to produce a newline, tab, double quote or backslash character, respectively. If more than one unescaped character is enclosed in quotes, the noun is a list of characters (see below), also known as a string. -
Symbols are start with a backtick (`) and are followed by an optional name. Names must start with
.
or a letter, and may contain letters, digits or.
. Symbols are mainly useful as handles to variable names or keys in dictionaries. -
Lists are a sequence of nouns. If several numbers have spaces separating them, they form a list:
2 78 3
Symbols work the same way, but the spaces are optional:
`bread `apples `soap `bread`apples`soap
Boolean lists are suffixed with
b
and require no spaces between elements:10010b 1 0 0 1 0
Byte lists consist of
0x
followed by an even number of hexadecimal digits. Each byte is interpreted as the equivalent ascii character for prettyprinting purposes if it is in the printable range (32-127). If only two digits are provided, this literal form will produce a lone character, rather than a 1-length list.0x414243 0x6a6b
Mixed-type lists are enclosed in
()
and each element should be separated by a semicolon:(1 2 3;"food";`b)
-
Dictionaries are enclosed in
[]
and consist of key-value pairs separated by semicolons (;) in which keys are backtick-less symbols and values are any expression:[a:34;b:"feed me"]
-
Functions are enclosed in
{}
and consist of one or more expressions separated by semicolons (;). When evaluated, functions execute these expressions left to right and return the value of their final expression. The special namesx
,y
andz
are implicit arguments to a function. If all three are present, the function takes 3 arguments. If onlyx
andy
are present, the function takes 2 arguments. If onlyx
is present, the function takes 1 argument. Functions are applied to arguments with[]
or simply by juxtaposing the function and the argument in the case of single-argument functions:mean:{(+/x)%#x} mean[4 7 18] {x*x} 5
Functions may alternatively begin with a list of explicit named arguments, enclosed in square brackets and separated by semicolons. The following expressions are semantically equivalent:
{x*2+y} {[apple;square] apple*2+square}
The special variable
o
will contain a reference to the current (enclosing) function. This is generally used for writing recursive definitions:{(o;o)}[] ({(o;o)};{(o;o)})
The variable
o
can be used as an infix operator within function definitions:{$[x;(x-1)o(y,2**|y);y]}[3;2] 2 4 8 16
The symbol $
, when used with 3 or more argument expressions is cond
. Much like the Lisp construct, cond
considers argument expressions two at a time. If the first in a pair evaluates to a truthy value, the second in the pair is evaluated and returned. Otherwise it continues with the next pair. If no conditions match, the final value is returned. For the purposes of cond
, anything except 0
, 0x00
or ()
is truthy.
$[1;"A";0;"B";"C"]
"A"
$[0;"A";0;"B";"C"]
"C"
Note that cond
is a special top-level construct which evaluates subexpressions only according to the above rules. Side-effecting subexpressions make this more obvious:
$[0;a:50; 1;a:25; a:13];
a
25
You can often program without this type of conditional statement, but the short-circuiting behavior of cond
is vital for writing recursive procedures:
r: {$[1<#x; |r'x; x]};
r (1 2;(3 4;5 6 7))
((7 6 5
4 3)
2 1)
K has 19 primitive verbs which are each represented as a single character: +-*%!&|<>=~,^#_$?@.
Each has different behavior when used as a monad (with one argument) or as a dyad (with two arguments). Verbs behave as dyads if there is a noun immediately to their left, and otherwise they behave as a monad. Sometimes it is necessary to disambiguate, so using a colon (:
) as a suffix will force a verb to behave as a monad. Verbs have uniform right-to-left evaluation unless explicitly grouped with ()
. If applied to nouns without a verb argument, the adverbs /
, \
and '
can behave as verbs.
Some verbs are atomic. A fully atomic verb penetrates to the atoms of arbitrary nested lists as arguments:
1 3 5+(3; 1 2; 5)
(4
4 5
10)
A right atomic verb only penetrates to the atoms of the right argument, leaving the left argument intact. Similarly, a left atomic verb only penetrates to the atoms of the left argument.
Verbs and adverbs which are not supplied with sufficient arguments behave as nouns, and can be passed around. A sequence of such verbs and adverbs is implicitly composed, forming a train. You may also hear a train be described as a tacit form, as it permits compositions which contain no explicit references to named variables. If the final verb of a train is dyadic, the train behaves as a dyad- otherwise it behaves as a monad. Here are some examples of trains:
(+) / dyadic, equivalent to {x+y}
(2+) / monadic, equivalent to {2+x}
(*<2*) / monadic, equivalent to {*<2*x}
(+/*) / dyadic, equivalent to {+/x*y}
See below for a complete reference to verb behaviors.
K has 6 primitive adverbs, some of which consist of two characters: '
, /
,\
, /:
, \:
and ':
. Adverbs take a verb as a left argument and apply it to a right or right and left noun argument in some special way. Some adverbs have several different behaviors based on the types of their arguments.
For the purposes of the adverb and verb references, the following conventions will be used:
a
: any atomn
: a numberc
: a characterl
: a listm
: monadic verb or functiond
: dyadic verb or function
For a dyadic verb, the names x
and y
refer to the left and right arguments, respectively. For a monadic verb, the name x
refers to the right argument.
As a general note, verbs which operate on numbers will coerce characters to their ascii values when applied.
+ - * % ! & | < > = ~ , ^ # _ $ ? @ . ' / \ ':
Monadic | Dyadic |
---|---|
+l is flip. Takes the transpose of matrices. Atoms are spread to match the dimension of other columns.
|
n+n is plus. Fully atomic.
|
-n is negate. Flips the sign of numbers. Right atomic.
|
n-n is minus. Fully atomic.
|
*l is first. Extracts the first element of a list.
|
n*n is times. Fully atomic.
|
%n is square root. Right atomic.
|
n%n is divide. Fully atomic.
|
!n is int. Generate a range from 0 up to but excluding N.
|
n!n is mod. Take y modulo x. Right atomic.
|
&l is where. Make N copies of sequential indices of elements. For a boolean list this gathers indices of nonzero elements.
|
n&n is min. Fully atomic. For booleans, effectively logical and.
|
|l is reverse.
|
n|n is max. Fully atomic. For booleans, effectively logical or.
|
<l is asc, also known as "grade up". Generate a permutation vector which would sort argument into ascending order.
|
n<n is less. Fully atomic.
|
>l is desc, also known as "grade down". Generate a permutation vector which would sort argument into descending order.
|
n>n is more. Fully atomic.
|
=l is group. Generate a dictionary from items to the indices where they were found.
|
a=a is equal. Fully atomic.
|
~n is not. Nonzero numbers become 0 and 0 becomes 1. Right atomic.
|
a~a is match. Returns 1 if x and y are recursively identical.
|
,a is enlist. Place item in a 1-length list.
|
a,a is concat. Join together lists or atoms to produce a list.
|
^a is null. Is this item a null? Right atomic.
|
l^a or l^l is except. Remove all instances of each of y from x.
|
#l is count. Atoms have count 1.
|
n#l or n#a is take. Truncate or repeat y to produce a list of length x. A negative x takes from the end of y.
Works like take, but creates an arbitrary dimensioned result based on x.
Equivalent to l@&m'l.
|
_n is floor. Right atomic.
|
n_l is drop. Remove x elements from the start of y. A negative x drops from the end of y.
The indices must be ascending.
Equivalent to l@&~m'l.
|
$a is string. Convert atoms into strings. Right atomic.
|
n$a is pad. Adjust strings to make them x characters long. If the string
is under x characters long, then it is right-padded with spaces; otherwise, characters are stripped from the end. A negative value pads/strips from the left. Mostly fully atomic, strings are treated specially.
Fully atomic.
|
?l is distinct. Produce a list of the unique elements in a list.
|
l?a is find. Determine the index of y in x. Returns 0N if not found. Right atomic.
Right atomic.
|
@a or @l is type. Returns a magic number indicating the type of the noun. General lists are 0, listy things are positive and non-listy things are negative.
|
x@y is at. Index a list or dictionary x, apply a single argument to a function x.
|
.l is value. Evaluate K expressions from strings.
|
l.a or l.l is dot-apply. Index at depth or apply a list of arguments to a function.
|
n/a |
l'a is bin. Perform a binary search for y in x. Right atomic. x must already be sorted.
|
n/a |
a/l is join. Place the character x between strings y.
|
n/a |
a\l is split. Break the string y apart at instances of character x.
|
n/a |
n':l is window. Create a sliding window of length x from y. If x is less then zero, then it is equivalent to 3':0,y,0. If x is zero, then this is equivalent to (1+#y)#().
|
As a general note, niladic functions may be used where monadic functions are valid adverb arguments; they will ignore any inputs.
m'l
is each. Apply the monad to each x, producing a new list. If x is an atom, this is equivalent to m@a
.
{2*x}'5 7 2
10 14 4
x d'y
is each dyad. Pair up values from x and y and apply them to the dyad, producing a new list. If x or y is an atom, spread it to the elements of the other sequence.
2 7 9{x,2*y}'1 3 4
(2 2
7 6
9 8)
(5),'1 3 4
(5 1
5 3
5 4)
d':l
is eachprior. Apply the dyad to each element of the list (left argument) and the element preceding that element in the list (right argument), producing a new list. Consistent with list indexing, the first element of the list will thus be paired up with 0N. Some primitive verbs result in a different special-cased initial value: +
, *
, -
and &
are provided with 0, 1, 0 or the first element of the sequence, respectively, and ,
is provided with only 1 parameter.
=':3 3 4 4 5
0 1 0 1 0
-':1 3 5 2 9
1 2 2 -3 7
,':2 3 4
(,2
3 2
4 3)
a d':l
lets you specify an explicit initial value for eachprior:
99,':2 3 4
(2 99
3 2
4 3)
n m':l
is stencil, which applies a monad to overlapping windows of some size on the list. This can be seen as a convenience for "each window":
3(,/$)':11 22 33 44
("112233"
"223344")
x d/:l
is eachright. Apply the dyad to the entire left argument and each right argument, producing a new list.
2 3,/:4 5 6
(2 3 4
2 3 5
2 3 6)
l d\:x
is eachleft. Apply the dyad to each left argument and the entire right argument, producing a new list.
2 3,\:4 5 6
(2 4 5 6
3 4 5 6)
d/l
is over, also known as foldl. Apply the dyad to pairs of values in x from left to right and carrying each result forward, reducing the list to a single value. Some primitive verbs result in a different special-cased value when applied to an empty list: +
, *
, |
and &
result in 0, 1, negative infinity or positive infinity, respectively.
+/4 5 2
11
|/()
-0w
x d/l
lets you specify an initial value for over:
4+/5 2
11
m/x
is fixedpoint. Repeatedly apply the monad to x until it stops changing or repeats its initial value. The scan form of this adverb is often useful for getting a better understanding of what is happening.
{_x%2}/32
0
n m/y
is for. Apply the monad to y, n times.
5{,x}/7
,,,,,7
m m/x
is while. Repeatedly apply the monad to x as long as the left monad applied to the result is true.
{x<100}{x*2}/1
128
d\l
is scan. Scan and its variants all behave identically to over, except they accumulate a list of intermediate results rather than just returning the final result. Apply the dyad to pairs of values in x from left to right and carrying each result forward.
+\4 5 6
4 9 15
x d\l
lets you specify an initial value for scan. Note that this value is not included in the results:
2*\3 2 9
6 12 108
m\x
is scan-fixedpoint. Repeatedly apply the monad to x until it stops changing or repeats its initial value and accumulate a list of intermediate results.
{_x%2}\32
32 16 8 4 2 1 0
{3!1+x}\2
2 0 1
n m\y
is scan-for. Apply the monad to y, x times and accumulate a list of intermediate results.
5{,x}\7
(7
,7
,,7
,,,7
,,,,7
,,,,,7)
m m\x
is scan-while. Repeatedly apply the monad to x as long as the left monad applied to the result is true and accumulate a list of intermediate results.
{x<100}{x*2}\1
1 2 4 8 16 32 64 128
The verbs ?
, @
and .
have special triadic and tetradic overloads in k6 to perform miscellaneous functions. This section will try to explain known overloads on a case-by-case basis.
?[l;x;v]
is splice. Replace the elements of l
in the interval given by x
with v
. x
must be a length-2 list.
?[1 2 3;1 1;4]
1 4 2 3
?["test";1 3;"u"]
"tut"
?["hello world";0 5;"goodbye"]
"goodbye world"
If v
is a monadic verb train or function, it is applied to the elements specified by the interval rather than simply replacing them:
?[2 7 9;1 2;2*]
2 14 9
?["a look back";2 6;|:]
"a kool back"
.[f;x;:]
is error trap. Call f
with the argument list x
. If any internal faults occur, return (1;e)
where e
is the error message as a string. If execution is successful, return (0;x)
where x
is the result of f.x
.
.[1+;,1;:]
0 2
.[1+;,`a;:]
(1
"number expected, found symbol.")
Beyond the standard verbs, K includes a number of named functions for useful but less common operations:
-
sin x
: Monadic, atomic. Calculate the sine ofx
.sin 0 .5 3.141 0 0.4794 0.0006
-
cos x
: Monadic, atomic. Calculate the cosine ofx
.cos 0 .5 3.141 1 0.8776 -1
-
exp x
: Monadic, atomic. Calculate the exponential function-e
to the powerx
.exp 1 5 12 2.7183 148.4132 162754.7914
-
log x
: Monadic, atomic. Calculate the natural logarithm ofx
.log 2.7183 5 10 1 1.6094 2.3026
-
prm x
: Monadic. Generate all permutations of the items of a listx
. Ifx
is a number, treat it the same as!x
:prm "AB" ("AB" "BA") prm 3 (0 1 2 0 2 1 1 0 2 1 2 0 2 0 1 2 1 0)
-
x in y
: Dyadic, left-atomic. Isx
a member ofy
?1 3 7 in 1 2 3 4 5 1 1 0