# Functions

In fi, all variables are modified using strict functions. For example, you can't use a normal coding expression like this in fi:

`let int test = int 20 + int 10 - int 5;`

Instead, we must use functions, for example:

`let int test = sub(add(int 20, int 10), int 5);`

With fi, all returned values MUST be used. For example:

`let int test = int 20;add(test, int 10); #Invalid, as int 30 is returned and unusedtest.add(int 10); #Valid​`

This returns a value of int 30 which is left unused and will cause a compilation error.

# Arithmetic functions

Returns the sum of two or more provided arguments, starting from left to right.

`let nat test = add(nat 1, nat 2, nat 3, nat 4); # Returns nat 10`

The Return type is defined by the inputs between the two values being evaluated:

`add(int, int, ...) 				=> intadd(int, nat, ...) 				=> intadd(nat, int, ...) 				=> intadd(nat, nat, ...) 				=> natadd(mutez, mutez, ...) 		    => mutezadd(timestamp, int, ...) 	    => timestampadd(int, timestamp, ...) 	    => timestamp`

This function can be used as standalone functions, or as a variable modifier.

## sub(mixed,...) returns mixed

Returns the difference of two or more provided arguments, starting from left to right.

`let int test = sub(nat 10, nat 5, nat 3, nat 1); # Returns int 1`

The Return type is defined by the inputs between the two values being evaluated:

`sub(int, int, ...) 				=> intsub(int, nat, ...) 				=> intsub(nat, int, ...) 				=> intsub(nat, nat, ...) 				=> intsub(mutez, mutez, ...) 			=> mutezsub(timestamp, int, ...) 		=> timestampsub(timestamp, timestamp, ...) 	=> timestamp`

This function can be used as standalone functions, or as a variable modifier.

## mul(mixed,...) returns mixed

Returns the product of two or more provided arguments, starting from left to right.

`let nat test = mul(nat 10, nat 5, nat 3, nat 1); # Returns nat 150`

The Return type is defined by the inputs between the two values being evaluated:

`mul(int, int, ...) 			=> intmul(int, nat, ...)		    => intmul(nat, int, ...) 	    	=> intmul(nat, nat, ...) 			=> natmul(mutez, nat, ...) 		=> mutezmul(nat, mutez, ...) 		=> mutez`

This function can be used as standalone functions, or as a variable modifier.

## div(mixed,...) returns mixed

Returns the product of two or more provided arguments, starting from left to right.

`let nat test = div(nat 100, nat 5, nat 10, nat 1); # Returns nat 2`

The Return type is defined by the inputs between the two values being evaluated:

`div(int, int, ...) 			=> intdiv(int, nat, ...)		    => intdiv(nat, int, ...) 			=> intdiv(nat, nat, ...) 			=> natdiv(mutez, nat, ...) 		=> mutezdiv(mutez, mutez, ...) 	    => nat`

This function can be used as standalone functions, or as a variable modifier.

## mod(mixed,...) returns mixed

Returns the remainder/mod of two or more provided arguments, starting from left to right.

`let nat test = div(nat 100, nat 5, nat 10, nat 1); # Returns nat 2`

The Return type is defined by the inputs between the two values being evaluated:

`div(int, int, ...) 			=> intdiv(int, nat, ...)		    => intdiv(nat, int, ...) 			=> intdiv(nat, nat, ...) 			=> natdiv(mutez, nat, ...) 		=> mutezdiv(mutez, mutez, ...) 	    => nat`

This function can be used as standalone functions, or as a variable modifier.

## abs(int) returns nat

Returns the absolute value (unsigned) of the input int, returned as a nat.

`let nat test = abs(int -20); # Returns nat 20`

## neg(nat|int) returns int

Returns the negative signed value of the input, as an int.

## sqr(mutez|nat|int) returns [same as input]

Returns the sqr of the input variable as the same type.

`let nat test = sqr(nat 10); #Returns 100`

# String & Byte functions

## concat(bytes|string,...) returns [same as input]

Returns the concatenated inputs as the same output type. When using concat, all arguments must be of the same type (either bytes or string). Similar to arithmetic functions, multiple inputs can be concatenated from left to right.

`let string HelloWorld = concat(string "Hello", string " ", string "World");`

This function can be used as standalone functions, or as a variable modifier.

## concat_ws(string seperator, string...) returns string

Returns the concatenated inputs using the first string as a separator.

`let string HelloWorld = concat(string " ", string "Hello", string "World");`

## slice(string|bytes, nat offset, nat length) returns [same as first argument]

Returns the slice string or bytes starting from offset for length.

## hash(bytes, ?algo) returns bytes

Returns the hashed bytes using the algorithm matching algo. Algo can be set to one of the following literals:

• blake2b

• sha256

• sha512

If algo isn't provided, blake2b will be used by default.

`let bytes test = hash(bytes 0x050000, sha512);`

## pack(data) return bytes

Data of any type can be packed into byte form, which can be used for other purposes (as well as unpacking).

`let bytes test = pack(nat 1);`

## unpack(bytes, type) return mixed

The opposite to unpack - the packed bytes must be provided, as well as the type of the packed data. Will return the unpacked bytes as type.

`let bytes test = pack(nat 1);let nat test2 = unpack(test, nat);`

## verify(bytes, signature, key) returns bool

Verify will evaluate if the signature matches the provided key and bytes. Returns a bool.

# Map/Set/List functions

All of these functions can be used as standalone functions, or as a variable modifier.

## in(map|bmap|set, mixed val) returns bool

For map and bmap, returns true if mixed val is a valid key that exists within the map/bmap, otherwise returns false. For sets, this returns true if val is a vlid element that exists within the set.

`let set[int] tset = new set(int);let bool test = tset.in(int 1); # False`

## length(map|list|set) returns nat

Returns the cardinal length/size of the map, list or set as a nat.

`let set[int] tset = new set(int);let nat test = tset.length(); # nat 0 `

## get(map|bmap, mixed val) returns mixed

Returns the element and type that corresponds to the map key val, or fails if it doesn't exist. We recommend using the in function first.

`let map[int=>string] tmap = new map(int, string);let string test = tmap.get(int 1); # Will throw an error`

## push(map|bmap, mixed key, mixed val) no return

Inserts or updates the element val with key. Does not return anything.

`let map[int=>string] tmap = new map(int, string);tmap.push(int 1, "Hello World");let string test = tmap.get(int 1); # string "Hello World"`

## push(set, mixed val) no return

Inserts or updates the element val. Does not return anything.

`let set[string] tset = new map(string);tset.push("Hello World");`

## drop(map|bmap|set, mixed val) no return

For maps and big maps, the element with the corresponding map key val is removed from the map. For sets, the element val is removed. Does not return anything.

`let set[string] tset = new map(string);tset.push("Hello World");tset.drop("Hello World");`

## pop(list) returns mixed

Returns the last item and type from list.

`let string[] tlist = new list(string);tlist.push("Hello");tlist.push("World");let string test = tlist.pop(); # string "World";`

# On-chain functions

## transfer(address|pkh|key_hash|key|contract *, mutez, ?data) no return

Executes an on-chain operation to the provided address sending amount mutez. If data is present, we also send this as the parameter. The contract type must match the type of the data (if provided).

Nothing is returned.

`transfer(SENDER, mutez 10);`

## delegate(?key_hash) no return

Sets the delegate for the contract - if key_hash is set than this is used, otherwise the contract is un-delegated if no argument is provided.

Nothing is returned.

`delegate();`

# Other functions

## isset(?mixed) returns bool

Returns true if the optional value is not empty, otherwise it returns false.

`let ?string test = to_optional(string "Hello World");let bool test2 = isset(test); # True`

## none(type) returns ?type

Returns an optional value of type that is empty.

`let ?string test = none(string);let bool test2 = isset(test); # False`