# Functions

**Encapsulate your Julia code into functions, for convenience and performance.**

Functions play a key role in structuring Julia code. Arguably, most programs in Julia are basically constructed by applying and composing functions.

**Structuring code into functions is also key for performance.** As Julia is structured around a JIT compiler, in order to get our code compiled we need to wrap it up inside a function. As a consequence, performance-critical sections of our code should always be written inside functions.

There are many ways to define and use functions in Julia. Let’s review them.

## Defining a function

As an example, let’s define a function that will evaluate the first \( N \) terms of the quadratic series

```
function sum_series(n)
x = 0
for k in 1:n
x = x + (1/k)^2
end
return x
end
```

After executing that code, we can call our function from the REPL, by typing:

```
sum_series(100000) # returns 1.6449240668982423
```

## One-line functions

In Julia, we can also define a function with a single line of code. For example, by doing:

```
sum_series2(N) = sum(1/n^2 for n=1:N)
```

We can then call it just like above:

```
sum_series2(100000) # returns 1.6449240668982423
```

## Functions with multiple outputs

An other common requirement is to be able to write functions which return multiple arguments. This can be done in Julia in a very straightforward manner.

```
function circle(r)
area = π * r^2
circumference = 2π * r
return area, circumference
end
a, c = circle(1.5)
```

What is happening under the hood is that the `circle`

function is returning a `tuple`

, and that `tuple`

is being destructured into two variables.

In fact, we can also call our `circle`

function and expect a single output (a tuple), and use it as follows:

```
shape = circle(1.5) # returns (7.0685834705770345, 2.356194490192345)
shape[1] # 7.0685834705770345
shape[2] # 2.356194490192345
a, c = shape # destructures the tuple as in the original
```

Note that tuples are inmutable structures: we won’t be able to modify the values of `shape`

. But we can modify the values of `a`

and `c`

.

## Functions which modify their input arguments

In Julia, values **are not copied** when they are passed to function. In particular, a function could change the content of input arguments. To let the caller know if this is indeed the case, it’s a convention to append an exclamation mark to names of functions that do modify their arguments.

```
function add_one!(x)
x = x + 1
end
x = 3
add_one!(x); # v is now 4
```

This notation is also used, for example, in the Plots.jl visualization library, to add more data to an existing `plot`

object.

## Anonymous functions

Sometimes we don’t need to assign a name to a function. For example, when we need to quickly define a function, to pass it as an argument to another function.

Let’s consider the following example. Let’s say we have written (or we are using) the following code which finds the root of a given function `f`

, with the secant method (see Wikipedia).

```
function secant(f,a,b,rtol,maxIters)
iter = 0
while abs(b-a) > rtol*abs(b) && iter < maxIters
c,a = a,b
b = b + (b-c)/(f(c)/f(b)-1)
iter = iter + 1
end
return b
end
```

Of course, this code can be applied to any function. We could define a function and pass it as an argument, or use anonymous functions as a shorthand.

For example, let’s call this secant procedure to find the so-called “golden ratio”, which is the positive root of the polynomial \( x^2 - x - 1 \). We can do this by resorting to an anonymous function, as follows:

```
φ = secant( x-> x^2 - x - 1, 1, 2, 1e-15, 10 )
```

## Organizing functions into multiple files

In order to put our functions in a separate file, we first create a new `myFunctions.jl`

file, where we only add our functions

```
function sum_series(n)
x = 0
for k in 1:n
x = x + (1/k)^2
end
return x
end
function other_function(n)
(...)
end
```

and then we can call this from another file by using the `include`

keyword. Then, Julia then behaves exactly in the same as if we had the functions defined within our current file.

For example, let’s consider that in addition to `myFunctions.jl`

, we have another file called `test_myFunctions.jl`

with the following content

```
include("myFunctions.jl")
x = sum_series(100000)
```

## Conclusion

This post covered the basics of how to structure computations in Julia with functions. There is a lot more to learn in this topic! Stay tuned as this is a growing and evolving series of tutorials.