A Very Quick Reference

## Overview

Kronos programs are built from *expressions* and *definitions*.

An expression describes a sequence of mathematical or logical operations to produce a result from one or more initial values.

A definition *binds* an expression to a *symbol*. Subsequently, the symbol can be used to refer to the expression.

## Expressions

x + 3 * Crt:cos(y)

This expression describes a computation of a numerical result from the initial values of x, 3 and y.

Expressions are essentially a sequence of *tokens*. In the example above, the tokens are x, +, 3, * and Crt:cos(y).

Tokens are delimited by either white space or parentheses.

### Constants

Constants are plain numbers. A plain number is interpreted as a 32-bit floating point real number. Prefices and suffices can be used to enforce a different number type;

3i /* constant 3 as a 32-bit integer */ 3.1415d /* constant 3.1415 as a 64-bit real */ 9q /* constant 9 as a 64-bit integer */ #6.54 /* special type of number Invariant */

##### Invariant

Invariant numbers are prefixed with '#'.

Such numbers are important for two reasons; they never change during program execution and can thus be heavily optimized. The compiler can also use them for metaprogramming purposes.

### Literals

String literals can be entered as quoted strings;

"Hello World"

### Symbols

Symbols can be names for variables or functions. They can include alphanumeric characters as well as some punctuation characters.

Each symbol must start with an alphabetical character.

x MyVariabeName some-symbol123 attention!

### Tuples

A tuple is a grouping of data. Such grouping is expressed with parentheses.

(1 2 3 4 5)A tuple of five numbers.

[1 2 "text" 3]A list containing numbers, a string and a number.

[(1 2) (10 20) (100 200)]A list of three vectors

### Functions

A symbol and a tuple without an intervening whitespace is considered a function.

The symbol names the function, and the tuple specifies the arguments passed to the function.

Factorial(#5) Add(5 4) Algorithm:Reduce(Add 1 2 3 4)Some function calls

(somesymbol(1 3)) /* this is a function call in parentheses */ (somesymbol (1 3)) /* this is a 3-member tuple! */Whitespace is important to disambiguate functions and tuples!

### Infix Functions

The Kronos parser translates some infix operators to functions for a more readable syntax. The following relations apply:

a + b /* Add(a b) */ a - b /* Sub(a b) */ a * b /* Mul(a b) */ a / b /* Div(a b) */ a > b /* Greater(a b) */ a < b /* Less(a b) */ a == b /* Equal(a b) */ a != b /* Not-Equal(a b) */ a >= b /* Greater-Equa(a b) */ a >= b /* Less-Equal(a b) */ a & b /* And(a b) */ a | b /* Or(a b) */ a ^ b /* Xor(a b) */

Because some infix characters are legal token characters, infix operators must always be surrounded by whitespace:

much - fun /* becomes Sub(much fun) */ much-fun /* refers to symbol 'much-fun' */

## Definitions

Actual programming in Kronos happens via definitions. For example, to hear an audio output, you define the audio-generating function.

### Symbols

Defining symbols is called *binding*.

Definitions are done via the equality sign.

a = 5 /* a is now 5 */ x = y / Sqrt(z) /* an expression tied to x */

Defined symbols are unlike variables in two accords; they actually contain the *expression* itself, rather than the value it results in. Secondly, typical to functional languages, once defined, they can never change.

#### Tie-in

Multiple symbols can be defined at once by defining a .

(a b c) = (1 2 3) /* a is now 1, b is 2... */

Tie-in is mostly useful when you receive a tuple that is bound to a symbol. The tuple can be deconstructed with a partial tie-in:

/* suppose list = (1 2 3 4 5) */ (x xs) = list /* x is now 1, xs is (2 3 4 5) */

Together with recursion, partial tie-in is used for loop-like constructs.

#### Ignore-binding

You can use '_' as a special symbol that never actually gets defined. Useful as a part of a tie-in, you can use it to ignore certain parts of the tuple.

someSurroundSignal = (l1 c1 r1 ls1 rs1 lfe) (l2 _ r2 _) = someSurroundSignal

In this exampe, l2 and r2 were bound to l1 and r1, while the rest of the elements are just ignored.

The first '_' corresponds to c1 and the second one to the tuple (ls1 rs1 lfe).

### Functions

Function definitions look like so;

MyFunction(x y z) { MyFunction = x + y + z }

The first line contains the function name and the argument tuple. In the consequent wavy brackets, the function bodies are given by way of defining a symbol eponymous to the function.

This particular example computes the sum of three numbers.

To call the function, attach an argument tuple;

MyFunction(1 2 3) /* returns 6 */

If you refer to the function name without arguments, it evaluates to the *definition* of the function itself. This way, you can use function definitions as data.

#### Polymorphism

Multiple definitions for a function can be given at once. This allows the function to behave differently according to its arguments.

SumNumbers(numbers) { (a b) = numbers SumNumbers = a + b /* second form */ (x y z) = numbers SumNumbers = x + y + z }

This function can sum either three or two arguments.

Polymorphism is often most useful in the case of recursion:

SumNumbers(numbers) { SumNumbers = numbers /* second form */ (n ns) = numbers SumNumbers = n + SumNumbers(ns) }

This function can sum any number of arguments; while the 'numbers' argument can be tied-in to (n ns), the function calls itself with 'ns' as the argument and adds the result to 'n'. At some point, 'numbers' is going to be a single number, at which point the first definition will be used instead.