# Functions

Once you start writing lots of code, you may wish to find a way to organise and structure things to make them tidier and easier to understand. Functions are a very powerful way to do this. They give us the ability to give a name to a bunch of code. Let’s take a look.

## Defining functions

    define :foo do
      play 50
      sleep 1
      play 55
      sleep 2
    end

Here, we’ve defined a new function called `foo`. We do this with our old friend the do/end block and the magic word `define` followed by the name we wish to give to our function. We didn’t have to call it `foo`, we could have called it anything we want such as `bar`, `baz` or ideally something meaningful to you like `main_section` or `lead_riff`.

Remember to prepend a colon `:` to the name of your function when you define it.

## Calling functions

Once we have defined our function we can call it by just writing its name:

    define :foo do
      play 50
      sleep 1
      play 55
      sleep 0.5
    end

    foo

    sleep 1

    2.times do
      foo
    end

We can even use `foo` inside iteration blocks or anywhere we may have written `play` or `sample`. This gives us a great way to express ourselves and to create new meaningful words for use in our compositions.

## Functions are remembered across runs

So far, every time you’ve pressed the Run button, Sonic Pi has started from a completely blank slate. It knows nothing except for what is in the buffer. You can’t reference code in another buffer or another thread. However, functions change that. When you define a function, Sonic Pi remembers it. Let’s try it. Delete all the code in your buffer and replace it with:

    foo

Press the Run button - and hear your function play. Where did the code go? How did Sonic Pi know what to play? Sonic Pi just remembered your function - so even after you deleted it from the buffer, it remembered what you had typed. This behaviour only works with functions created using `define` (and `defonce`).

## Parameterised functions

You might be interested in knowing that just like you can pass min and max values to `rrand`, you can teach your functions to accept arguments. Let’s take a look:

    define :my_player do |n|
      play n
    end

    my_player 80
    sleep 0.5
    my_player 90

This isn’t very exciting, but it illustrates the point. We’ve created our own version of `play` called `my_player` which is parameterised.

The parameters need to go after the `do` of the `define` do/end block, surrounded by vertical goalposts `|` and separated by commas `,`. You may use any words you want for the parameter names.

The magic happens inside the `define` do/end block. You may use the parameter names as if they were real values. In this example I’m playing note `n`. You can consider the parameters as a kind of promise that when the code runs, they will be replaced with actual values. You do this by passing a parameter to the function when you call it. I do this with `my_player 80` to play note 80. Inside the function definition, `n` is now replaced with 80, so `play n` turns into `play 80`. When I call it again with `my_player 90`, `n` is now replaced with 90, so `play n` turns into `play 90`.

Let’s see a more interesting example:

    define :chord_player do |root, repeats|
      repeats.times do
        play chord(root, :minor), release: 0.3
        sleep 0.5
      end
    end

    chord_player :e3, 2
    sleep 0.5
    chord_player :a3, 3
    chord_player :g3, 4
    sleep 0.5
    chord_player :e3, 3

Here I used `repeats` as if it was a number in the line `repeats.times do`. I also used `root` as if it was a note name in my call to `play`.

See how we’re able to write something very expressive and easy to read by moving a lot of our logic into a function!