Getting Started - maxkatzmann/hydra GitHub Wiki

Welcome to the Hydra wiki!

In the following we explain how to use Hydra to create drawings in the hyperbolic plane.

Getting Started with Hydra

Hydra interprets code line by line. You are allowed to have at most one statement in each line. Consequently, there is no need for an indicator (like ;) to separate statements. For example, the following Hydra code defines a variable a and assigns a value of 5.0 to it.

var a = 5

On the other hand, the following statements would be invalid and can not be interpreted:

var = 5 var b = 0 // Invalid assignment. There must only be one assignment per statement.
var a // Invalid assignment. Use 'a = 10.0' or 'var a = 10.0' to assign a variable.

Variables

As we have seen above, variables are defined using the keyword var. Once a variable is defined, the value it contains can be accessed or new values can be assigned to it:

var a = 5 // a = 5
var b = a + 2 // b = 7
a = 2 * b // a = 14

Numerical values are internally represented as Doubles. Note that you cannot assign a value to an undefined variable, which means you always need to define a variable using the var keyword, and assign an initial value to it, before further usage. It is, however, not allowed to define the same variable twice. Meaning the following code would lead to an error:

var a = 5
var a = 5 // Error in line 2: Redefinition of: 'a'.

Variables can be any combination of letters and numbers. Additionally, variables names can contain '_' but not at the beginning! This pattern is reserved for so called hidden variables, which will be introduced later.

Expressions

Hydra supports mathematical expressions containing the operators + (addition), - (subtraction), * (multiplication), and / (division). Multiplication and division operators are interpreted before addition and subtraction operators. Parentheses can be used to change the order of interpretation.

var a = 5 * 3 + 2 // a = 17
a = 5 * (3 + 2) // a = 25

Currently, Hydra supports one mathematical constant M_PI, which is internally represented with C++'s M_PI. Additionally, there is no support for the unary minus operator at the moment. However, 0 - x works just fine.

Functions

In the following we explain how built-in functions work. Hydra supports a collection of mathematical functions like exp(x:) which evaluates the exponential function at the passed parameter x:

var a = exp(x: 3.4) // a = e^3.4 = 29.964100

All functions that take parameters have the following form: function(parameter1: value1, parameter2: value2, ...). The parameter names must not be omitted. An example of a built-in function that takes two parameters is random(from:to:) which returns a number that is uniformly distributed within the passed bounds:

var a = random(from: 0.0, to: 2.0 * M_PI)

For a list of built-in functions, see Built-In Functions.

Additionally, Hydra supports the definition of custom functions using the following syntax.

func functionName(parameter1, parameter2) {
    ...
}

This function is then called as

functionName(parameter1: value1, parameter2: value2)

A custom function automatically returns the result of the last statement in the function. For example the code

func printAndReturnRandom() {
     var r = random(from: 0, to: 5)
     print(message: "The number is: \(r)\n")
     r
}

var s = printAndReturnRandom()
print(message: "Can confirm: \(s)\n")

May lead to an output like

The number is: 0.164877
Can confirm: 0.164877

Note, that it is important to define the function before calling it for the first time. As can be seen above, strings can contain the contents of variables using the escape sequence \(), i.e., the string "My number is \(1.5)" is the same as "My number is 1.5".

Initializations

Besides primitive numbers, Hydra has a built-in type called Pol that represents a polar coordinate. A Pol object is defined by its radius r and angular coordinate phi. The initialization of a Pol object looks just like a function call: Pol(r:phi:):

var origin = Pol(r: 0.0, phi: 0.0)

Property Access

The properties of a non-primitive object are accessed using .-notation.

var point = Pol(r: random(from: 0.0, to: 10.0), phi: M_PI / 4.0) // A point with a random radius
var radius = point.r // The radius of the point

Loops

Hydra supports range-based for-loops using the following notation:

for i in [L, S, U] {
    ...
}

There i is the loop variable , L is the lower bound, S is the step size and U is the upper bound. The range includes the lower bound. The range only includes the upper bound, if i = U at some point during the execution. The loop variable i may be manipulated in the loop. Hydra also supports nested loops.

for i in [0, 1, 3] {
    print(message: "\(2.0 * i)\n")
}
// 0
// 2
// 4
// 6

for i in [0, 2, 5] {
    print(message: "\(i * i)\n")
}
// 0
// 4
// 16

for i in [0, 1, 2] {
    for j in [0, 1, i] {
        print(message: "\(i + j)\n")
    }
}
// 0
// 1
// 2
// 2
// 3
// 4