# # Function

Functions are a very important element of ABS, as they are the core of userland customizations.

A function is declared with the following syntax:

``````f(x, y) {
x + y
}
``````

As you might notice, the return statement is implicit. You can make it explicit, but we advise not to, in order to keep your code as concise as possible:

``````f(x, y) {
return x + y
}
``````

Most languages use a more "explicit" identifier for functions (such as `function` or `func`), but ABS favors `f` for 2 main reasons:

• brevity
• resembles the standard mathematical notation everyone is used to (x ↦ f(x))

Functions can be passed as arguments to other functions:

``````[1, 2, 3].map(f(x){ x + 1}) # [2, 3, 4]
``````

and they can be assigned to variables as well:

``````func = f(x){ x + 1}
[1, 2, 3].map(func) # [2, 3, 4]
``````

Scoping is an important topic to cover when dealing with functions:

``````a = 10
func = f(x){ x + a }

f(1) # 11
a = 20
f(1) # 21
``````

ABS supports closures just like mainstream languages:

``````func = f(x) {
f(y) {
x + 1
}
}

# can also be expressed as

func = f(x) {
return f(y) {
return x + 1
}
}
``````

## # Named functions

You can create named functions by specifying an identifier after the `f` keyword:

``````f greet(name) {
echo("Hello \$name!")
}

greet(`whoami`) # "Hello root!"
``````

As an alternative, you can manually assign a function declaration to a variable, though this is not the recommended approach:

``````greet = f (name) {
echo("Hello \$name!")
}

greet(`whoami`) # "Hello root!"
``````

Named functions are the basis of decorators.

## # Optional parameters

Functions must be called with the right number of arguments:

``````f greet(name, greeting) {
echo("\$greeting \$name!")
}
greet("user")
# ERROR: argument greeting to function f greet(name, greeting) {echo(\$greeting \$name!)} is missing, and doesn't have a default value
# 	[1:1]	greet("user")
``````

but note that you could make a parameter optional by specifying its default value:

``````f greet(name, greeting = "hello") {
echo("\$greeting \$name!")
}
greet("user") # hello user!
greet("user", "hola") # hola user!
``````

A default value can be any expression (doesn't have to be a literal):

``````f test(x = 1){x}; test() # 1
f test(x = "test".split("")){x}; test() # ["t", "e", "s", "t"]
f test(x = {}){x}; test() # {}
y = 100; f test(x = y){x}; test() # 100
x = 100; f test(x = x){x}; test() # 100
x = 100; f test(x = x){x}; test(1) # 1
``````

Note that mandatory arguments always need to be declared before optional ones:

``````f(x = null, y){}
# parser errors:
# 	found mandatory parameter after optional one
# 	[1:13]	f(x = null, y){}
``````

## # Accessing function arguments

Functions can receive a dynamic number of arguments, and arguments can be "packed" through the special `...` variable:

``````f sum_numbers() {
s = 0
for x in ... {
s += x
}

return s
}

sum_numbers(1) # 1
sum_numbers(1, 2, 3) # 6
``````

`...` is a special variable that acts like an array, so you can loop and slice it however you want:

``````f first_arg() {
if ....len() > 0 {
return ...[0]
}

return "No first arg"
}

first_arg() # "No first arg"
first_arg(1) # 1
``````

When you pass `...` directly to a function, it will be unpacked:

``````f echo_wrapper() {
echo(...)
}

echo_wrapper("hello %s", "root") # "hello root"
``````

``````f echo_wrapper() {
echo(..., "root")
}

echo_wrapper("hello %s %s", "sir") # "hello sir root"
``````

## # Supported functions

### # call(args)

Calls a function with the given arguments:

``````doubler = f(x) { x * 2 }
doubler.call([10]) # 20
``````

### # str()

Returns the string representation of the function:

``````f(x){}.str()
# f(x) {
#
# }
``````