# Functions

## Writing a function

Coding a function in `etch` is straightforward.

All `etch` programs run from a `main()` function.

In the example below, we declare a function `myFunction()` and call it from `main()`.

```function main()

myFunction();

endfunction

// declare the function called from main()
function myFunction()

printLn("hello");

endfunction
```

## Parameter and return types

The iterative `fibonacci` function below takes a parameter `n: Int32` which is a 32 bit integer type named `n`.

The function will return an `Int32` and declares this with `: Int32`.

```function fibonacci(n: Int32) : Int32

var a = 0;
var b = 1;
var temp = 0;

for(i in 0:n)
temp = a;
a = b;
b = temp + b;
printLn(toString(a));
endfor

return a;

endfunction

// call fibonacci from main()
function main()

fibonacci(10);

endfunction
```

## Recursion

Below is an example of the fibonacci function implemented with recursion.

Warning

Take care with recursion in smart contract code.

```function fibonacci(n: Int32) : Int32

if(n <= 1)
return n;
else
return (fibonacci(n-1) + fibonacci(n-2));
endif

endfunction

function main()

var nterms = 10;

for (i in 0:nterms)
printLn(toString(fibonacci(i)));
endfor

endfunction
```

## Pass by reference

All variables in `etch` are passed by reference.

Attempting to reassign the value of a primitive variable passed to another function will cause a compilation error.

```function main()

var original_value = 10;
printLn(original_value);

change_value(original_value);
printLn(original_value);

endfunction

function change_value(value :Int32)

// value = 20; // error: assignment operand is not writeable. Failed to compile.

endfunction
```

The same is true of complex types.

```function main()

var myArray = Array<Int32>(5);
change_value(myArray);

endfunction

function change_value(value :Array<Int32>)

// value = Array<Int32>(3); // error: assignment operand is not writeable. Failed to compile.

endfunction
```

However, this is not the case with object types such as `State`.

```function main()

var myState = State<Int32>("balance", 10);
printLn(myState.get());

change_value(myState);
printLn(myState.get());

endfunction

function change_value(state :State<Int32>)

state.set(30);

endfunction
```

And `Array`.

```function main()

var myArray = Array<Int32>(5);
myArray[0] = 40;
myArray[1] = 41;
myArray[2] = 42;
myArray[3] = 43;
myArray[4] = 44;

printLn(toString(myArray[2]));
change_value(myArray);
printLn(toString(myArray[2]));

endfunction

function change_value(myArray :Array<Int32>)

myArray[2] = 100;

endfunction
```

Reassigning a primitive type to a new variable does not affect the original.

```function main()

var x = 10;
printLn(x);

change_value(x);
printLn(x);

endfunction

function change_value(value :Int32)

var y = 20;
y = value;
printLn(y);
y = 20;

endfunction
```
However, reassigning an object and changing any of its values does affect the original.

```function main()

var myArray = Array<String>(2);
myArray[0] = "hello";
printLn(myArray[0]);

change_value(myArray);
printLn(myArray[0]);

endfunction

function change_value(myArray :Array<String>)

var newArray = Array<String>(2);

newArray = myArray;
newArray[0] = "goodbye";

endfunction
```

## Utility functions

### Random

You can currently generate non-deterministic, random, signed and unsigned integers and floats.

There is one restriction: the beginning value of the range must be less than the end value.

```function main()

// var randUInt8 = Rand(0u8, 1000u8); // error: unable to find matching function for 'Rand'
// printLn(toString(randUInt8));

// unpermitted range
// var rand_test = Rand(100u16, 0u16); // runtime error: Invalid argument: Rand(a, b) must satisfy a < b

var randUInt16 = Rand(0u16, 1000u16);
// printLn(toString(randUInt16));

var randUInt32 = Rand(0u32, 1000u32);
printLn(toString(randUInt32));

var randUInt64 = Rand(0u64, 1000u64);
printLn(toString(randUInt64));

// var randInt8 = Rand(0u8, 1000u8);
// printLn(toString(randInt8));

var randInt16 = Rand(0i16, 1000i16);
// printLn(toString(randInt16));

var randInt32 = Rand(0i32, 1000i32);
printLn(toString(randInt32));

var randInt64 = Rand(0i64, 1000i64);
printLn(toString(randInt64));

var randFloat32 = Rand(0.0f, 1000.0f);
printLn(toString(randFloat32));

var randFloat64 = Rand(0.0, 1000.0);
printLn(toString(randFloat64));

endfunction
```

### Print

`printLn()` is available for printing variables to the console.

`print()` is available without a line break.

If the variable is a string, you don't have to cast it before printing, otherwise you should cast it with `toString()`.

Note

`etch` strips out all `printLn()` statements in a release environment. This means that logs and other miscellaneous debug code never finds its way onto ledger shards.

### Sysargs

The following `System` functions `Argc()` and `Argv()` return the number of arguments to `vm-lang` and their value.

• `System.Argc()`
• `System.Argv()`

Note

Coming soon: common utility maths functions such as `pow()`, `exp()`, `Abs()`, `Sine()`, `Cosine()`, etc.

## Type casting functions

• `toInt8()`
• `toInt16()`
• `toInt64()`
• `toByte()`
• `toUInt16()`
• `toUInt32()`
• `toUInt64()`
• `toFloat32()`
• `toFloat64()`
• `toString()`

For example:

```function main()

var x = 10;
var y = toByte(x);
var z = toInt8(x);
var a = toInt16(x);
var b = toInt32(x);
var c = toInt64(x);
var d = toUInt16(x);
var e = toUInt32(x);
var f = toUInt64(x);
var g = toFloat32(x);
var h = toFloat64(x);
// var i = toFixed32(x); // error: unknown symbol 'toFixed32'
// var j = toFixed64(x); // error: unknown symbol 'toFixed64'

endfunction
```

## Annotations

`etch` smart contract code includes annotated functions:

• `@init` is a constructor method that initialises the contract.

• `@action` is a function which defines transactions on the ledger that change state.

• `@query` is a function that allows you to query data residing on the ledger.

## Getters and setters

Getters and setters are available for `State` types.

• `set()`
• `get()`