# Functions #

Stylus features powerful in-language function definitions. Function definitions appear identical to mixins; however, functions may return a value.

## Return Values #

Let's try a trivial example: creating a function that adds two numbers.

``````add(a, b)
a + b
``````
``````add(a, b)
a + b
``````

We can then use this function in conditions, in property values, etc.

``````body
``````
``````body
``````

Rendering:

``````body {
}
``````
``````body {
}
``````

## Argument Defaults #

Optional arguments may default to a given expression. With Stylus we may even default arguments to earlier arguments!

For example:

``````add(a, b = a)
a + b

// => 15

// => 20
``````
``````add(a, b = a)
a + b

// => 15

// => 20
``````

Note: Since argument defaults are assignments, we can also use function calls for defaults:

``````add(a, b = unit(a, px))
a + b
``````
``````add(a, b = unit(a, px))
a + b
``````

## Named Parameters #

Functions accept named parameters. This frees you from remembering the order of parameters, or simply improves the readability of your code.

For example:

``````subtract(a, b)
a - b

subtract(b: 10, a: 25)
``````
``````subtract(a, b)
a - b

subtract(b: 10, a: 25)
``````

## Function Bodies #

We can take our simple `add()` function further. Let's casting all units passed as `px` via the `unit()` built-in. It reassigns each argument, and provides a unit-type string (or identifier), which ignores unit conversion.

``````add(a, b = a)
a = unit(a, px)
b = unit(b, px)
a + b

// => 25
``````
``````add(a, b = a)
a = unit(a, px)
b = unit(b, px)
a + b

// => 25
``````

## Multiple Return Values #

Stylus functions can return several values—just as you can assign several values to a variable.

For example, the following is a valid assignment:

``````sizes = 15px 10px

sizes[0]
// => 15px
``````
``````sizes = 15px 10px

sizes[0]
// => 15px
``````

Similarly, we may return several values:

``````sizes()
15px 10px

sizes()[0]
// => 15px
``````
``````sizes()
15px 10px

sizes()[0]
// => 15px
``````

One slight exception is when return values are identifiers. For example, the following looks like a property assignment to Stylus (since no operators are present):

``````swap(a, b)
b a
``````
``````swap(a, b)
b a
``````

To disambiguate, we can either wrap with parentheses, or use the `return` keyword:

``````swap(a, b)
(b a)

swap(a, b)
return b a
``````
``````swap(a, b)
(b a)

swap(a, b)
return b a
``````

## Conditionals #

Let's say we want to create a function named `stringish()` to determine whether the argument can be transformed to a string. We check if `val` is a string, or an ident (which is string-like). Because undefined identifiers yield themselves as the value, we may compare them to themselves as shown below (where `yes` and `no` are used in place of `true` and `false`):

``````stringish(val)
if val is a 'string' or val is a 'ident'
yes
else
no
``````
``````stringish(val)
if val is a 'string' or val is a 'ident'
yes
else
no
``````

Usage:

``````stringish('yay') == yes
// => true

stringish(yay) == yes
// => true

stringish(0) == no
// => true
``````
``````stringish('yay') == yes
// => true

stringish(yay) == yes
// => true

stringish(0) == no
// => true
``````

note: `yes` and `no` are not boolean literals. They are simply undefined identifiers in this case.

Another example:

``````compare(a, b)
if a > b
higher
else if a < b
lower
else
equal
``````
``````compare(a, b)
if a > b
higher
else if a < b
lower
else
equal
``````

Usage:

``````compare(5, 2)
// => higher

compare(1, 5)
// => lower

compare(10, 10)
// => equal
``````
``````compare(5, 2)
// => higher

compare(1, 5)
// => lower

compare(10, 10)
// => equal
``````

## Aliasing #

To alias a function, simply assign a function's name to a new identifier. For example, our `add()` function could be aliased as `plus()`, like so:

``````plus = add

plus(1, 2)
// => 3
``````
``````plus = add

plus(1, 2)
// => 3
``````

## Variable Functions #

In the same way that we can "alias" a function, we can pass a function as well. Here, our `invoke()` function accepts a function, so we can pass it `add()` or `sub()`.

``````add(a, b)
a + b

sub(a, b)
a - b

invoke(a, b, fn)
fn(a, b)

body
``````
``````add(a, b)
a + b

sub(a, b)
a - b

invoke(a, b, fn)
fn(a, b)

body
``````

Yielding:

``````body {
}
``````
``````body {
}
``````

## Anonymous functions #

You can use anonymous functions where needed using `@(){}` syntax. Here is how you could use it to create a custom `sort()` function:

``````sort(list, fn = null)
// default sort function
if fn == null
fn = @(a, b) {
a > b
}

// bubble sort
for \$i in 1..length(list) - 1
for \$j in 0..\$i - 1
if fn(list[\$j], list[\$i])
\$temp = list[\$i]
list[\$i] = list[\$j]
list[\$j] = \$temp
return list

sort('e' 'c' 'f' 'a' 'b' 'd')
// => 'a' 'b' 'c' 'd' 'e' 'f'

sort(5 3 6 1 2 4, @(a, b){
a < b
})
// => 6 5 4 3 2 1
``````
``````sort(list, fn = null)
// default sort function
if fn == null
fn = @(a, b) {
a > b
}

// bubble sort
for \$i in 1..length(list) - 1
for \$j in 0..\$i - 1
if fn(list[\$j], list[\$i])
\$temp = list[\$i]
list[\$i] = list[\$j]
list[\$j] = \$temp
return list

sort('e' 'c' 'f' 'a' 'b' 'd')
// => 'a' 'b' 'c' 'd' 'e' 'f'

sort(5 3 6 1 2 4, @(a, b){
a < b
})
// => 6 5 4 3 2 1
``````

## arguments #

The `arguments` local is available to all function bodies, and contains all the arguments passed.

For example:

``````sum()
n = 0
for num in arguments
n = n + num

sum(1,2,3,4,5)
// => 15
``````
``````sum()
n = 0
for num in arguments
n = n + num

sum(1,2,3,4,5)
// => 15
``````

## Hash Example #

Below we define the `get(hash, key)` function, which returns the value of `key` (or `null`). We iterate each `pair` in `hash`, returning the pair's second node when the first (the `key`) matches.

``````get(hash, key)
return pair[1] if pair[0] == key for pair in hash
``````
``````get(hash, key)
return pair[1] if pair[0] == key for pair in hash
``````

As demonstrated below, in-language functions—paired with robust Stylus expressions—can provide great flexibility:

``````hash = (one 1) (two 2) (three 3)

get(hash, two)
// => 2

get(hash, three)
// => 3

get(hash, something)
// => null
``````
``````hash = (one 1) (two 2) (three 3)

get(hash, two)
// => 2

get(hash, three)
// => 3

get(hash, something)
// => null
``````