Repository: razetime/ngn-k-tutorial
Branch: main
Commit: 9ae81f5462f4
Files: 34
Total size: 122.8 KB
Directory structure:
gitextract_re9qb74d/
├── .github/
│ └── workflows/
│ └── publish-docs.yml
├── .gitignore
├── 00-preface.md
├── 01-intro.md
├── 02-working-with-arrays.md
├── 03-functions-and-variables.md
├── 04-index-apply.md
├── 05-adverbs.md
├── 06-numbers-and-logic.md
├── 07-more-adverbs.md
├── 08-dicts-table-strings.md
├── 09-special-forms.md
├── 10-io.md
├── 11-debug-errors.md
├── 12-thinking-in-k.md
├── 13-a-prelude.md
├── 14-sudoku.md
├── 15-tables-files.md
├── 16-c-api.md
├── code/
│ ├── 01.k
│ ├── 02.k
│ ├── 03.k
│ ├── 04.k
│ ├── 05.k
│ ├── 06.k
│ ├── 07.k
│ ├── 08.k
│ ├── 16/
│ │ ├── Makefile
│ │ ├── add.c
│ │ └── add.k
│ ├── matmul.k
│ ├── rh.k
│ └── sudoku.k
└── readme.md
================================================
FILE CONTENTS
================================================
================================================
FILE: .github/workflows/publish-docs.yml
================================================
name: Publish docs
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
paths:
- '**.md'
# Allow manual runs from Actions tab
workflow_dispatch:
permissions:
contents: read
pages: write
id-token: write
concurrency:
group: "pages"
cancel-in-progress: false
jobs:
build:
name: Build docs
runs-on: ubuntu-latest
container:
image: docker://pandoc/latex:latest
options: --entrypoint=sh
steps:
- name: Setup Pages
id: pages
uses: actions/configure-pages@v4
- name: Checkout
uses: actions/checkout@v4
- name: Prepare output dir
run: |
apk add tar
mkdir output
- name: build_epub
run: |
pandoc --from gfm+attributes --to epub3 ??-*.md --number-sections --epub-title-page=false --toc --metadata title="ngn/k tutorial" --metadata author="razetime" --output output/ngn_k_tutorial.epub
- name: build_html
run: |
pandoc --from gfm+attributes --to chunkedhtml ??-*.md --number-sections --epub-title-page=false --toc --metadata title="ngn/k tutorial" --metadata author="razetime" --output docs.zip
cd output
unzip ../docs.zip
rm ../docs.zip
- name: build_pdf
run: |
pandoc --from gfm+attributes --to pdf ??-*.md --number-sections --epub-title-page=false --toc --metadata title="ngn/k tutorial" --metadata author="razetime" --output output/ngn_k_tutorial.pdf
- name: Upload artifact
uses: actions/upload-pages-artifact@v3
with:
path: output
deploy:
needs: build
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
================================================
FILE: .gitignore
================================================
*.epub
================================================
FILE: 00-preface.md
================================================
# Preface {.unnumbered}
You may access this book in the following formats:
- [Website](https://razetime.github.io/ngn-k-tutorial)
- [PDF](https://razetime.github.io/ngn-k-tutorial/ngn_k_tutorial.pdf)
- [EPUB](https://razetime.github.io/ngn-k-tutorial/ngn_k_tutorial.epub)
This book would not have been possible without the help of
[ngn](https://ngn.codeberg.page)'s dedicated work
on maintaining and teaching ngn/k, alongside many of the people in the
community who have contributed to the process of documenting and improving K.
I would like to thank all the people involved directly and indirectly with this
project.
================================================
FILE: 01-intro.md
================================================
# Introduction
Welcome to K!
K is an array-oriented programming language. Although this term may sound new, K comes from a family of
programming languages which date back to APL in the 1960s. You may already know a popular object-oriented
language such as Python or Java, so why should you learn K?
Other languages may have array programming capabilities, such as Julia or Python+NumPy, but there are few
things which compare to the joy of thinking and using K fluently. K and the APL family of languages push the
horizons of what a programming language should look like, and how it should be used. Using a tool that is
designed for its job has its own profound benefits, and K proves that rule very well. If you are looking for a
new way to look at programming and you want to have fun, you are in the right place.
Part of K's design was to improve upon some of APL's issues. At a glance, the most noticeable improvements are:
- You can type K on an ordinary QWERTY keyboard with no extra software.
- K emphasizes general purpose programming more than mathematics, which simplifies the steep learning curve of
APL's more math oriented sides.
- K adds and removes features on every iteration of its design. This lets it refine its design better than
languages which are forced to maintain backward compatibility, like APL, or even Python.
Each one of K's major iterations is called a *dialect*. In this tutorial, we
will learn about [ngn/k](https://codeberg.org/ngn/k), an open source
implementation of the K6 dialect. Learning ngn/k will give you the
fundamentals required to understand any K dialect.
K takes some time and effort to learn, just like any language. However, K is designed to be simple. Most of K's
basic concepts can be finished in an afternoon. Some parts of K will be hard to digest coming from a different
language background, but with a little focused practice and this beautiful tutorial, I can assure you that you
will be able to do great things with K.
To start with K, first understand how it uses "right to left" evaluation instead of operator precedence rules.
Take this simple math expression:
`2 * 2 + 3`
You might think to do `2 * 2` first, then add 3, which equals 7. However, K does not care about primary school
rules like PEMDAS. K evaluates from right to left:
`2 * 2 + 3` = `2 * (2 + 3)` = 10.
If you want the result to be 7, then you can add parentheses:
```
(2 * 2) + 3
```
...or you can reorder the operations so the multiplication is performed first:
```
3 + 2 * 2
```
The easiest way to run ngn/k is to go to the online interpreter, available at https://ngn.bitbucket.io/k/.
I recommend using the online interpreter's REPL available at https://ngn.bitbucket.io/k/#r until you get
comfortable with K. If you like running things locally, then feel free to build the interpreter from source:
https://codeberg.org/ngn/k/.
Let's start with a Hello World:
```
"Hello, World!"
```
K will automatically display the result of every line in your program as K data. This means that you can safely
paste the result of a K expression into your program, and use it later.
To prevent K from repeating everything you say to it, you can add a semicolon to the end of your line. For
example,
```
"Hello, World!";
```
will do absolutely nothing!
To actually display a string without K's formatting, you can do this:
```
/ an actual hello world program
` 0:"Hello, World!"
```
In this program, \` 0: is the equivalent of a print statement in any other language. It will print
a simple character array given to it with a newline at the end. You can change it to \` 1: if you
want to display without a newline.
The line starting with a `/` is a comment. You can also use comments inline.
Reminder: K's "operators" have no precedence. So the interpreter reads "Hello World" first, then
0:, then the backtick.
The other major part of our Hello World program is the character array, which brings us to the lego bricks of
the array-based language: the arrays.
The things that you can put in an array are called **Nouns**. These can be:
- Numbers, which can be simple integers or floating point numbers.
- Characters, which are enclosed in double quotes
- Symbols, which are a series of alphanumeric or `.` characters preceded by a backtick, like `` `.symbol123``.
- Symbol names cannot start with a number.
- Symbols can be made from arbitrary strings using double quotes: `` `"symbol with spaces"``
- Other Arrays
- Functions and dictionaries, which we will discuss later.
**Verbs** are primitive functions, written with a single character. When you put a verb inside an array, K
converts it to a noun. A verb can take one or two arguments, and can have multiple meanings based on what data
the verb is given. Verbs are equivalent to operators in other languages.
**Adverbs** are primitive higher-order functions, written with one or two characters. An adverb takes one or two verbs on the left and produces a new verb with modified functionality. Some adverbs also behave like verbs if they are not given a verb argument. Adverbs bind first, and they are always evaluated first. Before verbs are executed from right to left, adverbs must be paired with their respective arguments.
The default way of defining multi-element arrays is as follows:
```
(noun1; noun2; noun3)
```
In scripts, you can also use a newline and a space instead of semicolons to separate array elements, so:
```
(noun1
noun2
noun3)
```
is also valid array syntax.
A single element array of any type can be defined with the verb `enlist`, which is `,`.
```
,1
,"a"
,`symbol
```
It's important to understand that just `"a"` is a character, not a string. `,"a"`, however, is an array contraining the character `"a"`. Now to officially introduce you to your first K verb: enlist.
### `,x` Enlist
**Symbol:** `,`
**Args:** `, any_value`
**Description:** Create an array containing `x`.
Strings/character arrays can be made by putting multiple characters in double quotes, as you saw in the Hello World example. A single character string cannot be made with double quotes, since a single character in quotes is considered a character, as shown earlier.
```
"Hello, world!"
"This is a K string"
```
You can escape a double quote inside a character array with a backlash. K supports C style escape sequences in its strings, and you can refer to this table for the basic escapes:
| Escape | Character
| ------ | ---------
| `\\` | `\`
| `\n` | newline
| `\"` | `"`
| `\t` | tab
Arrays of symbols are created by juxtaposing the symbols together, with no spaces between them.
```
`a`b`c
`symbol`list
```
A list of numbers separated by spaces is a numeric array. All of the following are numeric arrays:
```
45 56 67
420 69
1 2 3
```
Numbers (and **only** numbers) separated by spaces will be treated as numeric arrays. This behaviour in K is called *stranding*.
One special thing about K's arrays is that some operations vectorize by default. Consider this:
```
1 2 3 + 4 5 6
```
gives `5 7 9`. This is also called a *conforming* operation. Conforming "penetrates" to the deepest subarrays in an array(atoms), so these:
```
1 + 2 3 4 -> 3 4 5
1 2 3 4 + (1;2 3;4;(5;6 7)) -> (2;4 5;7;(9;10 11))
```
are also valid K expressions. All basic arithmetic operators support conforming operations:
| Verb | What it does
| --------- | --------
| `+` | Add
| `-` | Subtract
| `*` | Multiply
| `%` | Divide
Some primitives in K conform only to one side. The ones that conform to the left are called left atomic, because they penetrate to the atoms of the left argument. The same goes for right atomic primitives.
Every verb in K can take 1 or two arguments. K programmers often call the 2-argument verbs *dyadic* and 1-argument verbs *monadic*. For example, these same tokens do very different things when they are given one argument on their right side:
| Verb | What it does
| --------- | --------
| `+` | Flip (Transpose)
| `-` | Negate
| `*` | First element of an array
| `%` | Square root
You can append a colon `:` after a verb to make sure that it executes with only one argument (monadic).
K has 22 primitive verbs and 6 primitive adverbs. They do different things depending on both the **type** and **number** of arguments given, leading to more than 70 unique functions the K programmer can use. Every primitive has an important usecase, and remembering these can be a challenge when you're starting out.
The overloads of each primitive verb are usually inter-related and are easy to understand. Once you get the hang of them, you will have the tools to create any program you like. We will cover the functionality of K's primitives, their overloads, and their basic usecases in this tutorial.
## Vocabulary from this lesson
- Noun: Any defined value in K.
- Verb: A primitive function that can be used infix, and operates on nouns.
- Adverb: A primitive higher order function that creates a new function from a given verb, or function noun.
Adverbs are part of K's syntax itself.
- Atom: Any value that is not an array (function, symbol, character, integer, float).
- Monad/Monadic Function: Single argument function.
- Dyad/Dyadic Function: Two argument function.
- Conforming Operation: An operation that works on the lowest level of nesting it can work with.
Most of K's verbs perform conforming operations.
## Exercises
1. Guess the result of `1 2 3 + 4`, Try it in the REPL. Then try `1 2 3 + 4 5`. What does K say, and why?
2. ngn/k has inbuilt documentation, available with `\` in the REPL. Try leafing through each help topic, and don't worry if you don't understand some things.
The inbuilt documentation is the most complete and up-to-date cheatsheet on ngn/k, which will be very useful in the coming chapters.
3. Define an array with one integer, one character and one symbol.
================================================
FILE: 02-working-with-arrays.md
================================================
# Working with Arrays
You know how to make arrays by hand. Now, it is time let the program make them for you.
The most basic and universal array creation verb is *range* (`!`):
### `!x` Range
**Symbol:** `!`
**Args:** `! number`
**Description:** Array with numbers from 0 to `x-1`.
Providing range with a single number gives an expected result:
```
!5
0 1 2 3 4
!3 3
(0 0 0 1 1 1 2 2 2
0 1 2 0 1 2 0 1 2)
```
But what does that second result mean? `!` generalizes to arrays of numbers, and this is called odometer.
What this does is generate all indices to index into an array that has the dimensions described in `x`.
Each column denotes one element.
### `!x` Odometer
**Symbol:** `!`
**Args:** `! numeric_array`
**Description:** Generate an array where each column denotes an index into an array which has dimensions `x`,
in row-major order.
Odometer always generates an array of the length it is given, or in K's notation, `#x`.
### `#x` Length
**Symbol:** `#`
**Args:** `# array/atom`
**Description:** Length of the given array. Returns 1 for atoms.
`#` when called dyadically is one of the most important verbs in K, called *reshape*.
Reshape lets you construct arrays with any number of dimensions:
```
3 3 3#4
((4 4 4;4 4 4;4 4 4)
(4 4 4;4 4 4;4 4 4)
(4 4 4;4 4 4;4 4 4))
3 3 2#!9
((0 1;2 3;4 5)
(6 7;8 0;1 2)
(3 4;5 6;7 8))
3 3#4
(4 4 4
4 4 4
4 4 4)
```
When there are not enough elements to fill all dimensions, `#` will repeat the elements of `y` till it is filled.
You can also omit dimensions in reshape:
```
3 0N#!9
(0 1 2
3 4 5
6 7 8)
```
Here, 0N (integer null) denotes the missing dimension.
K will try to fit all elements of the array in the smallest shape possible using the rest of the
dimensions. You can only omit one dimension in reshape.
Arrays are very flexible, first class values in K, and the more you buy into that concept,
the more fun you will have.
- Concatenation (`x,y`) joins two arrays together, or appends an atomic value to a array.
- Take (`x#y`) takes elements from the beginning or the end of a array
- Drop (`x_y`) drops elements from the beginning or the end of a array
- Cut (`x_y`) cuts (partitions) an array at the indices given.
- Delete (`x_y`) removes an element at a given index.
- Except (`x^y`) removes the elements of one array from another.
- Flip (`+x`) transposes a rectangular array.
- Distinct (`?x`) gets the unique elements of an array.
*Take* is a special case of Reshape where `x` is an atom, and `x` is lesser than the length of y (`#y`). It truncates the given array to length `x`. Negative `x` takes from the end.
*Drop* (`atom _ array`) does the same thing as take, except it removes `x` elements from the beginning or end.
*Cut* (`array _ array`) has some special behaviour: it ignores all elements till the first index in `x`, and then performs the cutting operation:
```
0 4_"feedface"
("feed";"face")
3 5_"adfdsfsdfa"
("ds"
"fsdfa")
```
*Delete* is `array _ index` and it is quite self explanatory.
*Except* (`array ^ array`) works like multiset difference: it removes the elements of `y` from `x`.
*Flip* (`+ array`) will error on non-rectangular arrays. However, a simple list consisting only of atoms will be enlisted.
```
+!4
,0 1 2 3
```
## Exercises
1. Convert `23 34 45 56` to `(,45; ,56)` using a single primitive.
2. Take the first five elements of `!9`, multiply them by 2, and put them back in the same place in !9.
3. Create the array `(6 8 10; 12 14 16)` using the primitives from this chapter. Try to find more than one way to do it.
================================================
FILE: 03-functions-and-variables.md
================================================
# Functions and Defining Variables
Now that you have an endless supply of array creation power, you now have to find a way to reuse those neat little arrays.
To define a variable, you type its name followed by a colon:
```
one: 1
```
Assigns the number 1 to the variable `one`. You can then use `one` anywhere you like. Yay!
To define multiple variables, you can put the variable names and their values in arrays:
```
(one; two; three): 1 2 3
1 2 3
one
```
If you have already defined a variable, you can then modify its value in the same way with the help of reassignment:
```
one: 2
one
2
```
Or modified assignment:
```
one +: 3
one
5
```
Modified assignment happens when a verb is given before the `:` symbol. The above statement is the same as `one: one + 3`.
You can assign any noun to a variable. For example, a dictionary can be named with:
```
dict: `a`b`c ! 1 2 3
```
Creates a dictionary `dict` with key-value pairs `` `a:1; `b:2; `c:3``
### `x!y` Create Dict
**Symbol:** `!`
**Args:** `array ! array`
**Description:** Create a dict with keys `x` and values `y`. `x` and `y` must be of equal length.
You can get values from a dict using square brackets: ``dict[`a]`` will give you `1`.
You can also assign functions to variables. The default method of defining functions in K is to create a lambda. For example:
```
plus:{x+y}
plus[1;2]
3
```
creates a function `plus` and passes the arguments 1 and 2 to it.
Function call syntax applies to Verbs as well, so `+[1;2]` is perfectly valid K (and a better way to put this).
But where do `x` and `y` come from? Every K function has three default arguments: `x`, `y` and `z`, if the arguments are not defined beforehand. To name the arguments yourself, you can put them in square brackets:
```
{[firstnum;secondnum] firstnum+secondnum}[1;2]
```
which also does the same thing. If you'd like to document your code, named arguments can be quite useful, but K functions are generally short enough to be understood with the default arguments.
Functions can have multiple statements separated by semicolons:
```
{x+y; x-y}[1;2]
-1
```
A function will always return its last expression, unless specifically told to with the help of `:`. Any expression which starts with a `:` will be returned, and immediately exit from a function:
```
{:x+y; x-y}[1;2]
3
```
A function can reference itself with the special variable `o`. A recursive factorial, for example, is
```
{$[x>1; x*o[x-1]; 1]}
```
Here, `>` is greater than. `<` is lesser than, and `=` is equal to.
So what does the `$` do? `$` is the K equivalent of an if statement. You *must* give `$` at least 3 arguments for a conditional.
effectively, this translates to the following pseudocode:
```
function(int x) {
if (x > 1) {
return x * o(x - 1);
} else {
return 1;
}
}
```
### `$[;;..]` If
**Symbol:** `$`
**Arguments:** Any number
**Description:** K's If statement. `$[condition; true; false]` or `$[condition1; true1; condition2; true2; ...; false]`.
So what is truth, and what is a falsehood?
The following table lists *all* falsy values in K. The rest are truthy.
| Type | Falsy
| ---------------- | -----
| Number | `0`
| Character | `"\0"`, `0x00`
| Symbol | `` ` `` (Empty symbol)
| Function | `(::)`
| Array | `()` (Any empty array)
| Dictionary | `()!()` (Any empty dictionary)
Although these may seem convenient, I highly recommend that your condition always returns 0 or 1.
To group multiple statements in an if-else, you can use a progn (lisp term), which is a bunch of statements inside square brackets:
```
{$[1;[a:x+y;a];0]}[5;6]
11
```
A progn, similar to a function, will always return its last statement unless told otherwise with the help of `:`.
## Scoping
You can define variables *within* functions as well, and you can use them within the function only. This means that
```
{a:5; {a}[]}
```
will give you an error. Instead, you can define a global variable using `::`:
```
{a::5; {a}[]}
```
However, this means that the entire program will have access to variable `a`. Global variables are best kept to a minimum in K, and we will see more ways to write our programs without them.
## Trains
A *train* is a way of representing simple function composition.
There are some important things to remember when writing trains:
- A train is a list of verbs, and their left arguments if applicable.
- A verb with a `:` after it will only be called with one argument. Without the colon, it is always called with two arguments. This applies to all places where you use verbs, but is especially useful in trains.
- A verb which does not have a `:` after it *must* have a left argument specified i.e `(+-)` is not a valid train but `(1+-)` is, since `+` is given left argument `1` and `+:-` is, since `+` only takes a single argument.
- Every primitive in train must have its *arity* specified with the help of `:`.
- The arity of the last verb of a train determines its arity. eg: `(f g h)` translates to `{f[g[h[x;y]]]}`, and `(f g h:)` translates to `{f[g[h[x]]]}`.
Trains are a way of representing really simple functions, where a list of functions is applied to one or two values. For example, here is a function that displays the first `x` odd numbers:
```
odds:{1+2*!x}
```
What this is doing is:
a) Generating a range 0..x-1 - `!x`
b) multiplying it by 2 (conforming) - `2*`
c) adding 1 to it (conforming) - `1+`
to convert this to a train, we have to specify arities:
- `!` is called monadically: `!:`
- `*` is called dyadically: `2*`
- `+` is called dyadically: `1+`
So what we finally get is:
```
odds: 1+2*!:
```
## Vocabulary from this lesson
- Variable: a name that is assigned a value.
- Lambda: General curly brace syntax for defining a function.
- progn: A block of statements which returns the value of its last statement, unless specified otherwise with `:`.
- Global variable: A variable that is available to the entire program, assigned with `::`.
- Dictionary: A noun that maps keys to values.
- Train: A sequence of composed verbs and their left arguments.
## Exercises
1. Define a lambda function that takes two numbers and subtracts 1 from their sum.
2. Define a train which has the same function as the one from Question 1.
3. Create the array `(1 2 3;4 5 6)` with the help of the verbs you learned in the previous chapter.
Then, make a dictionary with the first row as keys, and the second row as values.
================================================
FILE: 04-index-apply.md
================================================
# Indexing and Application
K is 0-indexed, which means arrays start at 0.
Indexing into an array takes the element at the given index and returns it.
Indexing into a dictionary takes the value that corresponds to a given key, and returns it.
Passing values to a function will return its corresponding result.
So why Arrays, dictionaries and functions together? Because they all do one single thing: They take a set of values, and return a single value. K hence treats them as the same thing: application.
The first method of application is called **at**.
### `f@x` At
**Symbol:** `@`
**Args:** `(func/array/dict) @ (array/atom)`
**Description:** Applies a noun `f` given on its left to a single argument `x` given on its right.
For a function, `@` treats `x` like it is a single value, and provides it to `f`.
`(-:) @ 1` gives `-1`.
For a dictionary or an array, `@` can take a single index:
``(`a`b`c!1 2 3) @ `a`` -> `1`
`67 78 89 @ 1` -> `78`
or an array of indices:
``(`a`b`c!1 2 3) @ `a`c`b`` -> `1 3 2`
`67 78 89 @ 0 2` -> `67 89`
All forms of application behave in this manner i.e. they will always index into atomic values and preserve the shape of the indices.
If you index outside of an array's length, you will get a null value corresponding to the type of the array:
`67 78 89 @ 56` -> `0N`
#### Implicit At Indexing
Implicit At Indexing is what happens when K sees two noun values in a row. The simplest way to understand this is with functions:
```
f:{1+x}
f 2
```
Here, K sees two nouns: `f` and `2`, so it applies `f` to `2`. `{1+x}2` and `{1+x}@2` do the exact same thing.
With arrays, you can expect to see stuff like this in a lot of K code:
```
"abcde"1 2
```
This is the same as `"abcde"@1 2`.
Many beginners find this ambigous as they are not fully clear on when K decides to do this. Let's say that we want to apply
`{1+x}` to the square root of 2. `%x` takes the square root, so we can do `{1+x}@%2`. But what about this?
```
{1+x} %2
```
Seems correct, right? K seems to think otherwise:
```
'type
{1+x}%2
^
```
The problem, which isn't obvious through the type error, is that you are not giving K two nouns one after the other.
```
{1+x} %2
|---| ||
| |+-noun
| +--verb
+------noun
```
So it is computing `{1+x}` divided by 2. It's important to remember that all of K's verbs have overloads for different numbers and types of arguments.
Basically, we have written it in a way that makes K use division instead of square root. To fix this, we can wrap the argument in parentheses,
making sure K sees a noun.
```
{1+x} (%2)
|---| |--|
| |
| +--noun
+--------noun
```
As you may have noticed, `{1+x}@%2` is simpler and shorter. Implicit indexing is a nice convenience in many other cases, so don't be afraid to use it!
### M-Expressions
The second form of application is called the M-expression, which may be familiar to people coming from the Lisp language. The M-expression is the most general form of application, and it assumes the form of `noun[args]`.
for a function call, you can do `f[a;b;c]`. Remember that function calls include semicolons.
this means that `+[1;2]` is the same as `1+2`, and you can effectively translate most K programs to use M-expressions only.
For an array, each argument indexes into a different dimension:
```
:a:3 3#1 2 3 4 5 6 7 8 9
(1 2 3
4 5 6
7 8 9)
```
The `:` at the beginning of the line is used to force a return value, so `a` gets printed. Now, with the help of M-expressions, you can do `a[1;2]` to get 6, and `a[0;0]` to get 1.
You can also omit a dimension in reshape using `0N` (a null value), like so:
```
3 0N#1 2 3 4 5 6 7 8 9
(1 2 3
4 5 6
7 8 9)
```
This will automatically split the array to fit in the given dimension constraint.
Like with `@`, you can also use arrays to index into any dimension: `a[0 1;2]` will give you `3 6`. Indexing always covers a rectangular area regardless of number of dimensions.
The final form of application is dot (`.`).
### `f.x` Dot
**Symbol:** `.`
**Args:** `noun . array`
**Description:** Applies a noun `f` to the arguments given in array `x`.
Dot application takes a noun on the left, and an array on the right. Each array element is taken as an argument.
`(+) . 1 2` is the same as `1 + 2`. Since `+` is a primitive, you must put it in parentheses to make it a noun before giving it to `.`.
**Note**: This behaviour where parenthesizing a verb creates a noun is called *nominalization*. It is mainly useful when a verb takes a function as an argument.
from the previous example, `a[1;2]` can be rewritten as `a . 1 2`, and `a[0;0]` is `a . 0 0`.
## Projections
K lets you omit arguments in application.
For functions, omitting arguments implies *partial application*:
`-[1;]` is a function that does `1-x` given an `x`.
`-[;1]` is a function that does `x-1` given an x. Basically, Projections will fill in values that you have left empty.
Projections are often used to pass in outside data to a function. This is a common method of omitting global variables, and passing data to inner blocks in K.
For example, this snippet should return a function that adds `a` to its argument.
```
f:{a:x;{a+x}}[1]
f[1]
'value
{a+x}
^
f[1]
^
```
here, `{a+x}` can't see the value of a, since `a` is outside of its block, and `a` is not global.
To fix this, we should instead pass `a` via projection:
```
f:{a:x;{x+y}[a]}[1]
f[3]
4
```
as compared to assigning to `a` globally (`f:{a::x;{a+y}}`), this keeps data within the function, and makes the function side-effect free. This is not only useful in K, but helps for any programming task in general.
We can also express this using the shorthand for partial application:
```
f:{a:x;+[a;]}[1]
f[3]
4
```
Now, if you remember from the beginning of this chapter, functions, arrays and dictionaries are all treated the same way in K. So projections can *also* apply to arrays and dictionaries!
For an array, a projection will take all elements from the nth dimension of an array:
```
3 3#!9
(0 1 2
3 4 5
6 7 8)
a:3 3#!9
a[1;]
3 4 5
a[;1]
1 4 7
```
For dictionaries, it will index into each nested dictionary within, and pull out the respective values:
```
(1 2 3!(3#,1 2 3!4 5 6))[;2]
1 2 3!5 5 5
```
## Vocabulary from this lesson
- Array: A list of elements mapped by indices.
- Dictionary: A list of elements mapped by K values.
- Function: A range of elements mapped by a K expression.
- Application: Getting a corresponding value from a given noun. Can be indexing or calling a function.
- Projection: A partially applied value, obtained by incomplete indexing.
## Exercises
1. Get the third column of the array `4 4#!16` using a projection. Then do it without a projection.
2. What happens when you project outside the domain of a noun? What are the differences in arrays, functions and dictionaries?
3. Write a function to add the first two elements of an array, but do it without indexing.
================================================
FILE: 05-adverbs.md
================================================
# Adverbs
Any respectable programming language will have its own forms of looping. You have already seen one form of looping in K's recursive functions
(`o`, function self reference). But even outside of recursion, you have seen K's looping through K's conforming operations, since they
move through each element of the arrays given to them.
Even with the power of recursion and branching, you will often find yourself in predicaments where these just
do not fit the task.
K's general design lends itself strongly towards some aspects of functional programming, and many of its adverbs help omit
loops and branching to solve tasks concisely and quickly.
If you are acquainted with functional programming already, `'` is map, `'` (dyadic) is zip, `/` is foldl, and `\` is scanl.
Hence, you will most likely never need recursion and branching in most situations.
Each (`'`) is an adverb which takes a function or verb and applies the function on each element of an array. Yes, the symbol for each is a single quote.
### `f' x` Each
**Symbol:** `'`
**Args:** `function' array`
**Description:** Apply function to each element of array.
For example, to reverse an array, we can use the `|` verb:
```
|'(1 2 3; 4 5 6)
(3 2 1
6 5 4)
```
### `| x` Reverse
**Symbol:** `|`
**Args:** `| array`
**Description:** reverse the elements of an array.
and to reverse each row of a 2D array, we can do `|'`:
```
a:3 3#!9
(0 1 2
3 4 5
6 7 8)
|'a
(2 1 0
5 4 3
8 7 6)
```
Each can also be used dyadically, and this form is called eachboth:
### `x f' y` Each Dyad
**Symbol:** `'`
**Args:** `array/atom function' array/atom`
**Description:** Apply dyadic function to each element of both arrays.
Each dyad zips two arrays together with a dyadic function, creating an array of the results. Both `x` and `y` must have the same length, unless either of them are atoms. When an atom is given, it is repeated to the length of the other argument (`5 f' 1 2 3` is the same as `5 5 5 f' 1 2 3`).
Each dyad and each are useful with functions that don't fully support conforming operations. For example, `!` (modulus) only penetrates to the atoms in its right argument, meaning `2 ! 3 4 5` will work, but `1 2 3 ! 3 4 5` will not. This is where `!'` comes in handy:
```
1 2 3 ! 3 4 5
1 2 3!3 4 5
1 2 3 !' 3 4 5
0 0 2
1 2 3 !' 5
0 1 2
```
Each dyad will repeat atoms to the length of the other argument, but sometimes you need an array to behave like an atom. Say, something like this:
```
1 2 3 !' (5 6; 5 6; 5 6) / not very ideal
(0 0
1 0
2 0)
```
One way to solve it is using a projection:
```
![;5 6]' 1 2 3
(0 0
1 0
2 0)
```
But the best way to do it is with eachleft(`\:`):
```
1 2 3 !\: 5 6
(0 0
1 0
2 0)
```
Eachleft applies a dyadic function to each element in the left array and the entire right argument.
### `x f\: y` Each Left
**Symbol:** `\:`
**Args:** `array/atom function\: array/atom`
**Description:** Apply dyadic function to each element of `x` and the whole of `y`.
For example, in `(a; b; c) f\: d` , we will get `(f[a;d]; f[b;d]; f[c;d])`.
The same applies for each right, which you can probably guess the symbol for (`/:`).
## Folds and Scans
Folds and scans are used to combine values from an array to produce one or many results.
### `x f/ y` Over (Fold from left)
**Symbol:** `/`
**Args:** `any dyad/ array`
**Description:** Fold array `y` from left with a dyadic function. `x` is optional.
There are many, many useful applications of folds, some of which are:
Fold | Verb | What it Does | Example
---- | ----------- | ---------------------------------- | ----------------
`+/` | Add | Sum | `+/1 2 3` -> `6`
`*/` | Multiply | Product | `*/3 4 5` -> `60`
`\|/`| Maximum | Maximum | `\|/3 5 1` -> `5`, `\|/1 0 0` -> `1`
`&/` | Minimum | Minimum | `&/3 5 1` -> `1`, `&/1 0 1 1` -> `0`
`,/` | Concatenate | Join all elements together (Raze) | `,/(1 2 3; 4 5 6)` -> `1 2 3 4 5 6`
These folds can also be used with an initial element, providing a fallback value:
```
0+/1 2 3
6
0+/()
0
1*/7 8 9
504
1*/()
1
```
With an initial element, these are fine. But what should happen *without* one?
```
+/()
0
*/()
1
|/()
-9223372036854775807
&/()
9223372036854775807
,/()
()
```
Sum and Product seem OK, but `|/` and `&/` have two meanings, since max and min mean different things for integers and booleans: the highest integer is what K returns by default, but the max and min booleans are 1 and 0. Hence, adding an initial element does the trick on booleans:
```
0|/()
0
1&/()
1
```
### `x f\ y` Scan (Scan from left)
**Symbol:** `\`
**Args:** `any dyad\ array`
**Description:** Fold array `y` from left with a dyadic function, producing intermediate results in an array. `x` is optional.
Scan is the same as fold, *except* it will also give you the intermediate values of the fold.
```
+\1 2 3 4 5 = 1 3 6 10 15
1 = 1
1+2 = 3
3+3 = 6
6+4 = 10
10+5 = 15
```
They are useful all by themselves, but they are also *very* useful for debugging fold functions and finding out what's going wrong midway.
```
*/7#1000
3875820019684212736
*\7#1000
1000 1000000 1000000000 1000000000000 1000000000000000 1000000000000000000 3875820019684212736
```
In the above example, we can see that integer overflow resulted in an "incorrect" result.
Scans are often useful with boolean functions (i.e. `<`, `=`, `>`, `&`, `|`). For example, to "turn off" all `1`s that appear after the first `0`, we can use:
```
&\1 1 1 0 0 1 1 1 0 1 0 1
1 1 1 0 0 0 0 0 0 0 0 0
```
Scans are also one of the main ways that K lets you access intermediate values from loops, making it widely useful. For example, to count or number runs of `1`s in some boolean input:
```
{y+x*y}\1 1 1 0 0 1 1 1 0 1 0 1
1 2 3 0 0 1 2 3 0 1 0 1
```
*Fold* and *scan* both use the first argument as initial value, and the rest of the arguments as input arrays. Note that scans of empty inputs return the (empty) input unchanged.
```
4+\1 2 3
5 7 10
0+\()
()
2*\7 8 9
14 112 1008
1*\()
()
```
## Iterated Fold and Scan
Fold and Scan both have overloads for more than two arguments. We will
be looking at examples of iterated scan only, since fold returns the
last result of scan anyway.
### `f\[x;...y]` Iterated Scan
**Symbol:** `\`
**Args:** `n-ad\[int;...arrays]`
**Description:** The length of `arrays` and the argument count of `n-ad` must
be the same.
- Do the following steps `x` times:
- Take the last `n` elements of `arrays`, call this `last`
- Add the result of `f.last` to the end of `arrays`
- Return the first `x+1` elements of `arrays`.
A simple use of this is to construct the fibonacci sequence:
```
+\[10;0;1]
0 1 1 2 3 5 8 13 21 34 55
```
There is another overload for this scan, where `x` is a list. In that case,
`x` is treated as an initial value of sorts, and the `arrays` are iterated
through. The first value is `f.(,x),arrays[;0]`, then `x` is set to that value.
The next iteration we use `arrays[;1]`, and so on.
You can see the difference with this example:
```
{x+y*z}\[3; 1 2 3; 4 5 6;7 8 9]
(1 2 3
4 5 6
7 8 9
29 42 57)
{x+y*z}\[1 2 3; 4 5 6;7 8 9]
(29 30 31
69 70 71
123 124 125)
```
Similar to ordinary fold/scan, the iterated versions simplify stateful
computation. However, these overloads tend to be more niche in their use.
## Vocabulary from this lesson
- Adverb: A syntactic form which acts like a higher order function on both nouns and verbs.
- Each: Zap each element with function
- EachBoth: Zip elements of two arrays with a function
- Eachleft and Eachright: Zip each element in one argument with the whole other argument with a function.
- Fold: Condense an array into a single value using a function.
- Scan: fold but outputs intermediate values as an array.
## Exercises
1. `|` when used with a single argument, reverses an array. Instead, reverse an array with the usage of a single fold.
2. Write a function to sum each row of an array.
3. Convert an array of base-2 digits to a base-10 integer using a fold. `f/1 0 1` -> `5`.
4. Write a function to get the prefixes of an array using an adverb: `f 1 2 3` -> `(,1;1 2;1 2 3)`
================================================
FILE: 06-numbers-and-logic.md
================================================
# Numbers and Logic
K does not like branching, but it likes logic very much. What this means is that you will be doing a lot of interesting things with integers in order to
avoid a branch.
The basic logical verbs of K are:
- `>` greater than
- `<` lesser than
- `=` equal to
- `~` exact match
- `~:` not
- `^` is null?
- `&` minimum / and
- `|` maximum / or
The other comparison related verbs outside of these are Grade Up (`<`) and Grade Down (`>`). These
functions are the sorting functions of K.
Grade Up and Down both return the indices of the values of the array in their final locations. Some would say that they generate a *permutation vector*.
The function`{x@` allows you to sort an array using any other array
as "weights", making it much more flexible.
All of the simple logical verbs, with the exception of *exact match* support conforming operations, and return `1` for true, and `0` for false. Since
booleans are also numbers in K, this lets us do some interesting things with them.
For example, let's say we want to increment all multiples of 2 in an array. Usually, one would check each number one at a time, and double it
if it were even.
To check if a number is even, we can use *mod* (`atom ! array`):
```
{2!x}2 3 4
0 1 0
```
We can then negate this to put 1s at the spots where even numbers are:
```
{~2!x}2 3 4
1 0 1
```
And then, add it to the array:
```
{x+~2!x}2 3 4
3 3 5
```
An important function that works on boolean arrays is *where* (`&`). Where takes a list of integers and
repeats their indices by their values:
```
& 1 2 3
0 1 1 2 2 2
```
What makes `&` interesting is that it can also repeat an index 0 times, thereby discarding it.
`&` can be used to filter elements based on a condition, like `{y@&x'y}`, which keep elements in `y` that satisfy predicate `x`.
+/
If you want the index of the first element that holds true under a condition, you can use `*&`. But a simpler and more efficient alternative is `?` (find).
### `x?y` Find
**Symbol:** `?`
**Args:** `array ? array`
**Description:** Index of each element of `x` in `y`. If not found, return `0N`.
`0N` is a null value, as described in *Arrays, Functions and Dictionaries*. A null value is generally used to
signify the absence of a value, and generally denote a special value in a given type. The most usual place
where null values are found are in indexing, where an out of bounds index returns a null value, and in find.
**Null Values for each data type**
| Type | Null |
| ---- | ---- |
|Integer | `0N` |
| Float | `0n` |
| Character | `" "` (Space) |
| Symbol | `` ` `` (no characters after backtick) |
| Function | `(::)` (identity function) |
`::` (monadic `:`) has been used in earlier chapters. It is used to force returns, and it always returns its argument without modification.
Sometimes, there is confusion between `0N` and `0n`, so you can use `@` (type) to distinguish between them:
```
@'(0N; 0n; " "; `; ::)
`i`d`c`s`u
```
`i` for integer, `d` for double, `c` for character, `s` for symbol, `f` for function and so on. If given an
array that is of a single type, these are capitalized. More info on ngn/k's types can be read about on the
[K Wiki](https://k.miraheze.org/wiki/Type).
Since these null values are not very easy to keep track of in an array, there are two primitives that are made specifically for dealing with them:
- Null? (`^`) which tells you which atoms in an array are null values (1 for null, 0 for not null).
```
^(1;0N;" ")
0 1 1
```
- Fill (`^`) which substitutes an element in places where there are null values.
```
"A"^(1;0N;" ")
(1
"A"
"A")
```
## Vocabulary from this lesson
- Grade Up/Down: A special type of sorting function that provides indices of the final sorted values in the array.
- Null Value: In K, every type has its own null value. Null values are placeholders, and all types of nulls can be detected with `^`.
## Exercises
1. Given an array `x` and a 'mask' array `y` consisting of zeroes and ones only, get the elements in `x` that are at the same positions
as the ones in `y`. `f[2 7 89 92 -123;0 1 0 1 1]` -> `7 92 -123`.
2. Create a dictionary from an array where the keys are the types of the elements in the array, and the values are the elements of the array.
3. Create a function with two arguments `x` and `y`, which takes the sum of `x[y]` without nulls.
================================================
FILE: 07-more-adverbs.md
================================================
# More Adverbs
Most of the time, you can manage to write good K programs with neat little eaches and folds and scans. But *some* algorithms choose not to use arrays. Some algorithms insist on themselves, and that's why K has its own version of explicit loops from other languages:
When given a number `n` and a function on the left, `/` acts as a *for* loop:
```
3 {1+x}/0
3
```
A for loop will apply a monadic function `n` times to a given value.
### `x f/ y` For
**Symbol:** `/`
**Args:** `int monad/ any`
**Description:** Apply function `f` `x` times to value `y`.
The same overload for `\` will produce the intermediate values of the *for*, like a scan:
### `x f\ y` For (Scan)
**Symbol:** `\`
**Args:** `int monad\ any`
**Description:** Apply function `f` `x` times to value `y`. Collect intermediate values of `y` in an array.
```
3 {1+x}\0
0 1 2 3
```
### `f g/ z` While
**Symbol:** `/`
**Args:** `monad monad/ any`
**Description:** Apply function `g` to `z` until `f[z]` is falsy.
When given two monadic functions on the left, `/` acts as a while:
```
{x<5}{1+x}/0 # While x is less than 5, add 1 to x.
5
```
The truthy and falsy values for while are the same as it is for If(`$`). You can rehash on what they are by checking [Part 3](#-if).
While-scan is quite self-explanatory (It provides the intermediate results of a while loop):
```
{x<5}{1+x}\0
0 1 2 3 4 5
```
## Other looping adverbs
The following are some of the more specialized looping adverbs in K which don't exactly fit in the previous two categories.
Let's start with *converge*:
```
{1_x}/1 2 3 4 / Drop the first element till the array no longer changes.
!0
```
Converge applies a verb to a value till the value no longer changes, and it's also called *fixpoint* due to that reason.
### `g/ z` Converge
**Symbol:** `/`
**Args:** `monad/ any`
**Description:** Apply function `g` to `z` until `g[z]` matches `z`.
### `x _ y` Drop
**Symbol:** `_`
**Args:** `integer _ array`
**Description:** Drop the first `x` elements of `y`. If `x` is negative, drop the last `x` elements.
*Converge-scan* is the scan(`\`) version of the same, and returns the intermediate results:
```
{1_x}\1 2 3 4
(1 2 3 4
2 3 4
3 4
,4
!0)
```
*eachprior* works like each, but instead applies a dyadic function to each element and the one before it, useful for many pairwise operations.
Since the first element of an array doesn't have anything before it, eachprior allows an optional left argument.
```
45 ,':1 2 3 4
(1 45
2 1
3 2
4 3)
-':1 2 3 4 / deltas
1 1 1 1
+':1 2 3 4
1 3 5 7
```
### `x f': y` Eachprior
**Symbol:** `':`
**Args:** `any dyad': array`
**Description:** for each element `b` in the array and the element `a` before it, calculate `f[b;a]`. If `x` is not provided, The first element is left unchanged.
Stencil is a more general version of what eachprior does:
```
3_:':"ABcdE"
("abc"
"bcd"
"cde")
```
The main difference between stencil and eachprior is that stencil applies a function to each n-length chunk, instead of passing in elements as arguments.
### `x f': y` Stencil
**Symbol:** `':`
**Args:** `int monad': array`
**Description:** apply `f` to each overlapping `x`-length chunk in array `y`.
To simply get the chunks of the array, we can use the identity function `::`: `num ::': array`, but there is a more convenient adverb for it: `x ': array`, which is called *window*.
### `x ': y` Window
**Symbol:** `':`
**Args:** `int ': array`
**Description:** get each overlapping `x`-length chunk in array `y`.
It may be quite surprising at first that window does not take a function, but be not afraid. Window behaves like any other function, and can be stored as well.
Why isn't *window* a verb, if it doesn't take a function, then? A K interpreter has to make the distinction because it's an overload of an adverb symbol.
## More adverb overloads
Now that you have seen window, we can look at some more neat adverbs:
- *base encode* (`int(x) \ int(y)`) converts a base-10 integer to an array of digits specified by the bases on the left. If `y` is an array, every number in `y` is encoded into a column.
- *base decode* (`int(x) / int(y)`) is the inverse of base encode.
- *split* (`string(x) \ string(y)`) splits `y` on string `x`.
- *join* (`string(x) / array(y)`) joins array `y` on string `x`.
- *binary search* (`array(x) ' any(y)`) does a binary search for each element of `x` in `y`. If you do not know what a binary search is, I recommend reading [this article](https://www.khanacademy.org/computing/computer-science/algorithms/binary-search/a/binary-search).
These *can* be implemented using the help of K's primitives (and K's philosophy does support that), but having them as symbols is quite convenient, since they are very commonly used.
## Not Really Adverbs
Two important functional programming primitives: `#`(filter) and `_`(filter-out) are not adverbs, since they don't quite fit in the overloads, but they are still quite important in general code.
Generally, filtering in K is done with the help of `&`(where), which repeats the index of each element by the value of each element:
```
&1 0 1 0 1
0 2 4
```
### `& x` Where
**Symbol:** `&`
**Args:** `& int_array`
**Description:** Repeat the index of each element in `x` by the value of each element in `x`.
this can be used in tandem with `@` to select values from an array:
```
("Raze"; "blah"; "ti"; "blah"; "me")@&1 0 1 0 1
("Raze"
"ti"
"me")
```
This can then be extended to use a condition on the array, keeping elements with length lesser than 5:
```
{x@&(5>#:)'x}@("K"; "looong"; "is"; "blaah"; "cool")
("K"
"is"
"cool")
```
*Filter* and *filter-out* are shorthands for this type of filtering. They expect a monadic function (given as a noun), and apply it to the whole array.
Then, the rest is done the same way as it is with `&` and `@`. The previous example can be written as:
```
((5>#:)')#("K"; "looong"; "is"; "blaah"; "cool")
("K"
"is"
"cool")
```
Remember that filter and filter-out are verbs, and hence expect function values and not verbs. this means `~#x` will not work, but `(~:)#x` will.
## Vocabulary from this chapter
- Window: a continuous run of elements in an array.
- Binary Search: A search that can find the position an element should be inserted after in a sorted array.
## Exercises
1. *Converge* (`g/ z`) is a special case of while. Implement your own converge function using a while.
2. Implement a function that converts a number to a list of digits in a given base (use while/fixpoint).
================================================
FILE: 08-dicts-table-strings.md
================================================
# Dictionaries, Tables, Strings and other Miscellaneous functions
Dictionaries and strings are not highly related, just that this chapter aims to show the rest of the verbs we have not covered in K,
which happen to be mainly relating to dictionaries and strings. Think of it as a rapid-fire explanation of their quirks.
## Dictionary Trivia
Dictionaries are an *ordered collections*. This means that many primitives which work on arrays work similarly on dictionaries. This includes:
- concat `,` (values in `y` overwrite values in `x`)
- reverse `|` (reverses key array and value array separately)
- map `'` (applies on values)
- first `*` (first value from key-value pair only)
- not `~`
- at `@` preserves the structure of the dictionary when given as the second argument.
- filter `#` and filter-out `_` (filter by value)
- where `&` (keys are repeated by values)
- grade up `<` and grade down `>` (sort keys by values)
Outside of these, the most complex of the dictionary functions is *group* (`=`), which group the indices of elements by their values.
For example, we can get the counts of the elements of an array:
```
:a:="aaaabbbbbaaaacccc"
"abc"!(0 1 2 3 9 10 11 12;4 5 6 7 8;13 14 15 16)
:b:#'a
"abc"!8 5 4
```
But the result is still a dictionary. Luckily, we can separate the keys with `!`, and the values with `.`.
```
!b
"abc"
.b
8 5 4
```
### Tables
Tables are flipped dictionaries. A dictionary can be flipped with `+` if:
- All keys are symbols
- All values are of the same length
Tables are dictionaries which allow indexing of columns with symbols, and rows using integers.
```
:a:+`a`b`c!3 3#!9
+`a`b`c!(0 1 2;3 4 5;6 7 8)
a[1]
`a`b`c!1 4 7
a[`a]
0 1 2
```
## String functions
`$` will cast any atomic value to a string. It also conforms to arrays and dictionaries:
```
$(`symbol; 123; {x+y}; 1 2 3!4 5 6)
("symbol"
"123"
"{x+y}"
1 2 3!(,"4";,"5";,"6"))
```
Dyadic `$` casts between different types:
```
`i$"dsfdasfsd" / Character to Integer
100 115 102 100 97 115 102 115 100
```
Monadic `_` floors numbers and lowercases strings:
```
_ (1.1;2.2;"ABC123")
(1
2
"abc123")
```
Dyadic `$` is pad with spaces. Padding conforms to atoms on the left, and strings on the right. Positive integers pad on the right, and negative integers pad on the left.
```
(3;4;(5;6))$("xy";"za";("bc";"cd"))
("xy "
"za "
("bc "
"cd "))
```
Some adverbs have useful string related overloads:
`x \ y` is split. Splits `y` on `x`.
```
" "\"string with spaces"
("string"
"with"
"spaces")
```
Naturally, `x / y` is join. Joins `y` on `x`.
```
"|"/("string";"without";"spaces")
"string|without|spaces"
```
Note that these adverbs *only* work on strings and nothing else.
### The Rest
#### Random number functions
Dyadic `?` when given two integers `x` and `y` generates `x` random integers from `!y`. If `x` is negative, this will be a
random permutation.
If `y` is an array, then it will deal `x` elements from it. Both of these allow repetitions.
Negative `x` will not allow repetition, and if the absolute value of `x` is greater than the length of `y`, then K will throw a length error.
Monadic `?` when given a single integer `x` will generate an array of random floats between 0 and 1 of length `x`,
Finally, `0N?x` where `x` is an array will shuffle `x`. If `x` is a number, then `!x` is used.
#### Base Decode and Encode (`\` and `/`)
ngn/k's base conversion adverbs are generalized: this means that you can do mixed-radix conversion and other cool things.
These adverbs will be familiar to APL programmers. Remember that these are adverbs, and not verbs. Some things you do with them may not work exactly as
expected.
The simplest use, and the most often use for this, is conversion to and from base 2:
```
2 \ 5
5
'rank
^
2 / 5
2
```
Wait a moment: that isn't right. Both of these results are wrong, and one of them is an error!
**Print debugging and comments**
The reason for this is one of K's limitations: `\` and `/` are interpreted differently based on the whitespace before them, and hence, the space before them changes their meaning.
Hence` \ 5` is hence interpreted as "pretty print 5 to stdout, and return its value", and `/ 5` is interpreted as a K comment.
In order to fix this, just remove the space.
```
2\5
1 0 1
2/1 0 1
5
```
For mixed radix, we can try some time conversion: hours, minutes and seconds to seconds:
```
24 60 60/2 46 40
10000
```
These adverbs also generalize to arrays, and can perform base conversion on multiple numbers:
```
2\5 6 7
(1 1 1
0 1 1
1 0 1)
2/(1 1 1;0 1 1;1 0 1)
5 6 7
```
#### Miscellaneous
Monadic `=` when given a single integer `x` will produce an identity matrix of side length `x`.
```
=3
(1 0 0
0 1 0
0 0 1)
```
Monadic `.` when given a string is eval. This will evaluate any string as K code. Although eval is a convenient method to parse K-like strings, it is slow and dangerous. Use it sparingly.
```
."1+2"
3
```
Dyadic `:` is right. it returns its right argument. `:` has many special meanings, so it is required to call
`:` with an M-Expression:
```
:[1 2; 3 4]
3 4
```
*no new vocabulary for this chapter.*
## Exercises
1. Write a function to convert seconds into hours, minutes and seconds, using `\`.
2. Write a function that takes a list of numbers `x` and a number `y`. Group the numbers in `x` into a dictionary based on whether they are multiples
of `y`. `f[1 3 5 9;3]` -> `(0;1)!(1 5;3 9)`
================================================
FILE: 09-special-forms.md
================================================
# Special Forms
A special form is a kind of verb that can perform specialized operations like control flow and global
modification.
Special forms are generally polyadic (more than 2 arguments).
You have already seen one special form: If (`$[;;..]`). We will be covering the rest of these special forms in this chapter.
## Amend (`@`)
### 3 Arguments (`@[x;y;z]`)
Given array `x`, indices `y` and monadic function `z`, Amend will apply `z` to the elements at indices `y`.
```
@["ABC";1 2;_:]
"Abc"
```
This is useful when you don't want to use assignment to modify specific elements in an array.
### 4 Arguments (`@[x;y;z;u]`)
Same as 3 argument amend, but `z` is dyadic, and `u` is the second argument provided to `z`.
```
@[2 3;0;+;4]
6 3
```
## Drill / Deep Amend (`.`)
### 3 Arguments (`.[x;y;z]`)
Similar to amend, `x` is an array, but `y` is a single multidimensional index, and `z` is a monadic function.
### 4 Arguments (`.[x;y;z;u]`)
Similar to 3 arguments, but with `z` dyadic, and `u` as the second argument.
## Try (`.[x;y;z]`)
An error handling mechanism.
`x` is a function, `y` is an array of arguments to `x`, and `z` is the function that is applied to the error message (see ch 11), if `x.y` fails.
Otherwise returns `x.y`. *Try* is most useful when you are in deeper levels of nesting in a function, and print debugging with ` \` (trace) is not
completely helpful.
```
.[+;1 2;"E:",]
3
.[+;1,`2;"E:",]
"E:'limit\n"
```
## Splice (`?[x;y;z]`)
Splices an array `z` between the indices given in `y` in array `x`. A very useful string function.
```
?["abcd";1 3;"xyz"]
"axyzd"
```
================================================
FILE: 10-io.md
================================================
# Input and Output
The main way of performing input and output in K is via its I/O verbs.
Every I/O verb has a different data format. However, the destination and source can be any of the following:
- the empty symbol `` ` ``, which irepresents STDIN and STDOUT
- An absolute path like `"/path/to/file"`
- A relative path Input, Output and System functions
The main method of I/O(input/output) in K is is via its input verbs: an input verb is denoted by a single digit, followed by a `:` symbol.
The number of an input verb denotes is data format:
- `0:` takes in arrays of character arrays (lines).
- `1:` takes in arrays of bytes.
You have already seen `0:` used for output in the [first chapter](#introduction).
Every I/O verb reads input when used monadically, and writes output when used dyadically. The general form is as follows:
`destination