Skip to content

Latest commit

 

History

History
870 lines (761 loc) · 26 KB

Manual.md

File metadata and controls

870 lines (761 loc) · 26 KB

oK Manual

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

Nouns

  • 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 names x, y and z are implicit arguments to a function. If all three are present, the function takes 3 arguments. If only x and y are present, the function takes 2 arguments. If only x 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
    

Conditionals

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)

Verbs

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.

Adverbs

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 atom
  • n: a number
  • c: a character
  • l: a list
  • m: monadic verb or function
  • d: 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.

Verb Reference

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.
  +(1 2;3 4)
(1 3
 2 4)
  +(5;3 4)
(5 3
 5 4)
n+n is plus. Fully atomic.
  3+4 5 6
7 8 9
  "ab"+5
102 103
-n is negate. Flips the sign of numbers. Right atomic.
  -(4 -10 8)
-4 10 -8
  -"b"
-98
n-n is minus. Fully atomic.
  23 9-5 10
18 -1
*l is first. Extracts the first element of a list.
  *5 19 8
5
*d extracts the first value from a dictionary.
  *[a:23;b:34]
23
n*n is times. Fully atomic.
  5 0 -3*2 2 1
10 0 -3
%n is square root. Right atomic.
  %25 7 100
5 2.6458 10
n%n is divide. Fully atomic.
  2 20 9%.5 10 2
4 2 4.5
!n is int. Generate a range from 0 up to but excluding N.
  !5
0 1 2 3 4
If N is negative, count up and exclude zero.
  !-3
-3 -2 -1
!l is odometer. Generate ranged permutations.
  !2 3
(0 0 0 1 1 1
 0 1 2 0 1 2)
!d is keys. List of keys from dictionary.
  ![a:3;b:4]
`a`b
n!n is mod. Take y modulo x. Right atomic.
  3!34 2 8
1 2 2
If n is negative, divide y by x and truncate. Right atomic.
  -3!5 6 27
1 2 9
l!l is map. Make dictionary from x keys and y value(s).
  `a`b!3 4
[a:3;b:4]
  4 5!6 7
4 5!6 7
&l is where. Make N copies of sequential indices of elements.
For a boolean list this gathers indices of nonzero elements.
  &2 3 1
0 0 1 1 1 2
  &1 0 0 1 0 1
0 3 5
&d indexes keys by where of values:
  &`a`b`c!1 0 2
`a`c`c
n&n is min. Fully atomic. For booleans, effectively logical and.
  3 5 7&0 6 9
0 5 7
|l is reverse.
  |"ABDEF"
"FEDBA"
|d reverses both keys and values in a dictionary.
  |[a:3;b:4]
[b:4;a:3]
n|n is max. Fully atomic. For booleans, effectively logical or.
  3 5 7|0 6 9
3 6 9
<l is asc, also known as "grade up".
Generate a permutation vector which would sort argument into ascending order.
  <5 8 2 7
2 0 3 1
<d sorts keys by their values:
  <[a:2;b:5;c:1]
`c`a`b
n<n is less. Fully atomic.
  2 3 5<1 0 6
0 0 1
>l is desc, also known as "grade down".
Generate a permutation vector which would sort argument into descending order.
  <5 8 2 7
1 3 0 2
>d sorts keys by their values:
  >[a:2;b:5;c:1]
`b`a`c
n>n is more. Fully atomic.
  2 3 5>1 0 6
1 1 0
=l is group. Generate a dictionary from items to the indices where they were found.
  =`c`a`b`b`a`c`a
[c:0 5;a:1 4 6;b:2 3]
=n is identity matrix. Generate an NxN identity matrix.
  =3
(1 0 0
 0 1 0
 0 0 1)
a=a is equal. Fully atomic.
  3 4 6=6
0 0 1
~n is not. Nonzero numbers become 0 and 0 becomes 1. Right atomic.
  ~(0 1;3 7 -1)
(1 0
 0 0 0)
~d applies to the values of dictionaries.
   ~[a:2 0;b:1]
[a:0 1;b:0]
a~a is match. Returns 1 if x and y are recursively identical.
  (`a;2 3 4)~(`a;2 3)
0
  (`a;2 3 4)~(`a;2 3 4)
1
,a is enlist. Place item in a 1-length list.
  ,1 2 3
,1 2 3
a,a is concat. Join together lists or atoms to produce a list.
  1,2 3
1 2 3
  2,3
2 3
  1,()
,1
Concatenating dictionaries favors values of y:
  [a:1;b:3],[b:5;c:7]
[a:1;b:5;c:7]
^a is null. Is this item a null? Right atomic.
  ^(5;`;0N)
0 1 1
l^a or l^l is except. Remove all instances of each of y from x.
  1 3 2 5 1 2 3^1 3 5
2 2
a^a or a^l is fill. Replace all nulls in y with x.
  "c"^(5;`;0N)
(5;"c";"c")
#l is count. Atoms have count 1.
  #4 7 10
3
  #[a:3;b:17]
2
  #"c"
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.
  2#"ABC"
"AB"
  6#"ABC"
"ABCABC"
  -2#"ABC"
"BC"
l#d selects the elements keyed in x:
  "fb"#"fab"!3 5 9
"fb"!3 9
l#l or l#a is reshape.
Works like take, but creates an arbitrary dimensioned result based on x.
  3 2#1 2 3
(1 2
 3 1
 2 3)
  3 2 2#1 2 3
((1 2
  3 1)
 (2 3
  1 2)
 (3 1
  2 3))
If the leading or trailing element of a length 2 rank vector is 0N, reshape treats that dimension as maximal:
  0N 3#!6
(0 1 2
 3 4 5)
  2 0N#!8
(0 1 2 3
 4 5 6 7)
m#l is filter.
Equivalent to l@&m'l.
  (2!)#!8
1 3 5 7
  (&/)#(1 0 1 1;1 1;0 1 0;1 2 1)
(1 1
 1 2 1)
  {x~|x}#("racecar";"nope";"bob")
("racecar"
 "bob")
Dictionaries are filtered by their values and result in dictionaries:
  (2!)#"abcdef"!2 3 4 5 6 7
"bdf"!3 5 7
_n is floor. Right atomic.
  _2.3 7.6 9 -2.3
2 7 9 -3
_c converts characters to lowercase. Right atomic.
  _"ABCdef!"
"abcdef!"
n_l is drop. Remove x elements from the start of y.
A negative x drops from the end of y.
  3_"ABCDE"
"DE"
  -3_"ABCDE"
"AB"
l_d filters out keys from a dictionary:
  `b`e_`a`b`c!3 5 9
`a`c!3 9
l_l is cut. Splits y at the indices given in x.
The indices must be ascending.
  0 4_"feedface"
("feed";"face")
  1 2 4_"feedface"
(,"e";"ed";"face")
m_l is filter-out.
Equivalent to l@&~m'l.
  (2!)_!8
0 2 4 6
  (&/)_(1 0 1 1;1 1;0 1 0;1 2 1)
(1 0 1 1
 0 1 0)
  {x~|x}_("racecar";"nope";"bob")
,"nope"
Dictionaries are filtered by their values and result in dictionaries:
  (2!)_"abcdef"!2 3 4 5 6 7
"ace"!2 4 6
$a is string. Convert atoms into strings. Right atomic.
  $120 4
("120";,"4")
  $`beef
"beef"
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.
  5$"beef"
"beef "
  -7$"beef"
"   beef"
2 3 4$("a";"b";"c")
("a "
 "b  "
 "c   ")
a$a is cast. Convert values to a different type based on a symbol.
Fully atomic.
  `i$"Hello."
72 101 108 108 111 46
  `c$72 101 108 108 111 46
"Hello."
  `f`i`b$31
31 31 1
A short list of conversion symbols:
  • `c: convert to character
  • `i: convert to integer
  • `f: convert to float (basically useless!)
  • `b: convert to boolean (bitwise AND with 1)
  • `: convert string(s) to symbol
?l is distinct. Produce a list of the unique elements in a list.
  ?(`a`b;3;`a`b;7;3)
(`a`b
 3
 7)
?n produces a list of x random floats from 0 up to but excluding 1.
  ?6
0.197 0.8382 0.1811 0.9084 0.6113 0.1958
l?a is find. Determine the index of y in x. Returns 0N if not found.
Right atomic.
  "XYZ"?"XYXZB"
0 1 0 2 0N
d?a generalizes find to look up the key in x associated with the value y.
Right atomic.
  (`a`b`c`d!23 14 9 5)?9 14
`c`b
n?n is random. Produce x random integers from 0 up to but excluding y.
  5?10
0 3 3 7 7
  5?10
3 5 2 7 9
n?l picks random elements from y.
  8?"ABC"
"ACBBCBCB"
n?c or n?c where c is a character will pick random elements from the 26 characters including and up from c. For example, 10?"A" will pick 10 random elements from ABCDEFGHIJKLMNOPQRSTUVWXYZ, and 10?"0" will pick 10 random elements from 0123456789:;<=>?@ABCDEFGHI. For n?n or n?l, if x is negative the result will pick abs(x) distinct items.
@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.
  @`a
-11
  @"d"
-10
  @()
0
x@y is at. Index a list or dictionary x, apply a single argument to a function x.
  3 7 8@0 1 1
3 7 7
  [a:4;b:7]@`a
4
  {x*x}@5
25
Invalid indices will produce 0N:
  [a:4;b:7]@`q
0N
  3 7 8@4
0N
.l is value. Evaluate K expressions from strings.
  ."1+2"
3
.d gives the values of a dictionary.
  .[a:11;b:22]
11 22
.f gives the bound environment of a function as a dictionary. See "bind". (This exists only in oK.)
  .{x+y}
[in:{[x;y]~^y?x}]
l.a or l.l is dot-apply. Index at depth or apply a list of arguments to a function.
  (2 3;4 5).(1 0)
4
  {x,2*y}.(3 5)
3 10
f.d is bind. Treat the dictionary as the new global scope for the function. (This exists only in oK.)
  f:{a+::x}.[a:100]
{[x]a::.`a+x}
  f 5
105
  f 20
125
  .f
[a:125]
n/a l'a is bin. Perform a binary search for y in x. Right atomic.
x must already be sorted.
  0 2 4 6 8 10'5
 2
   0 2 4 6 8 10'-10 0 4 5 6 20
 -1 0 2 2 3 5
n/a a/l is join. Place the character x between strings y.
  "|"/("a";"bc";"def")
"a|bc|def"
l/l is encode. Combine digits y in a base x into a single value.
  2 2 2/1 0 1
5
  10 10 10/3 4 5
345
n/a a\l is split. Break the string y apart at instances of character x.
  ","\"cat,dog,banana"
("cat"
 "dog"
 "banana")
l\n is decode. Split a number y into a given base x.
  2 2 2\5
1 0 1
  10 10 10\345
3 4 5
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)#().
  3':!5
(0 1 2
 1 2 3
 2 3 4)
  2':!5
(0 1
 1 2
 2 3
 3 4)

Adverb Reference

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.")

Builtins

Beyond the standard verbs, K includes a number of named functions for useful but less common operations:

  • sin x: Monadic, atomic. Calculate the sine of x.

        sin 0 .5 3.141
      0 0.4794 0.0006
    
  • cos x: Monadic, atomic. Calculate the cosine of x.

        cos 0 .5 3.141
      1 0.8776 -1
    
  • exp x: Monadic, atomic. Calculate the exponential function- e to the power x.

        exp 1 5 12
      2.7183 148.4132 162754.7914
    
  • log x: Monadic, atomic. Calculate the natural logarithm of x.

        log 2.7183 5 10
      1 1.6094 2.3026
    
  • prm x: Monadic. Generate all permutations of the items of a list x. If x 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. Is x a member of y?

        1 3 7 in 1 2 3 4 5
      1 1 0