# Functies

Zodra u veel code begint te schrijven, kan je als je wil, een manier vinden om dingen te gaan organiseren en structureren, om deze netter te maken en gemakkelijker te begrijpen. Functies zijn een zeer krachtige manier om dit te doen. Ze brengen ons de mogelijkheid om een naam te geven aan een bundel code. Laten we een kijkje nemen.

## Functies definiëren

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

Hier hebben we een nieuwe functie genaamd `foo` gedefinieerd. We doen dit met onze oude vriend het do/end blok en het magische woord `define` gevolgd door de naam die wij willen geven aan onze functie. We hoefde deze niet `foo` te noemen, we konden deze om het even wat noemen zoals `fiets`, `bal` of een ideale beschrijving zoals `refrein_stuk` of `lead_riff`.

Vergeet niet van een dubbele punt `:` bij de naam van je functie te voegen wanneer je deze definieert.

## Functies aanroepen

Eens we een functie hebben gedefinieerd kunnen we deze oproepen door gewoon zijn naam te schrijven:

    define :foo do
      play 50
      sleep 1
      play 55
      sleep 0.5
    end
    foo
    sleep 1
    2.times do
      foo
    end

We kunnen zelfs gebruik maken van ‘foo’ binnen iteratie blokken of overal waar we `spelen` of `samplen` hebben geschreven. Dit schenkt ons een geweldige manier om onszelf te uiten en nieuwe zinvolle woorden te gebruiken in onze composities.

## Functies worden onthouden langsheen het uitvoer commando

Tot nu toe was het zo, dat telkens als u de Afspeel-knop ingedrukte, Sonic Pi met een schone lei startte. Het weet weet van niets tenzij van wat er in de buffer zit. Je kan niet verwijzen naar code die in een andere buffer of een andere thread zit. Met functies veranderd dat. Wanneer je een functie definieert zal Sonic Pi zich deze herinneren. Laten we dit eens proberen. Verwijder alle code uit uw buffer en vervang het met:

    foo

Druk op de Afspeel-knop - en hoor je functie nu spelen. Zo zonder code? Hoe wist Sonic Pi wat het moest spelen? Sonic Pi herinnerde zich jouw functie - dus zelfs nadat je deze hebt gewist uit de buffer, het herinnerde zich wat jij had getypt. Dit gedrag werkt alleen met functies die zijn gemaakt met `define` (en `defonce`).

## geparametreerde functies

Interessant om weten ook is dat je net zoals je min als max waarden kan geven aan `rrand`, kan je ook jouw functies argumenten laten accepteren. Laat ons dat even bekijken:

    define :my_player do |n|
      play n
    end
    my_player 80
    sleep 0.5
    my_player 90

Dit is niet erg spannend, maar het illustreert wel de zaak. We hebben onze eigen versie van `play` genaamd ‘my_player’ die is geparametriseerd.

De parameters moeten na de `do` van het `define` do/end blok komen te staan, omringd door een sluisteken `|`en gescheiden door komma’s `,`. Om deze parameters te benoemen mag je elk woord gebruiken dat je maar wil.

Het zit ‘h allemaal in de `define` do/end blok. Je kan de parameternamen gebruiken zoals echte waarden. In dit voorbeeld speel ik de noot `n. Je kan deze beschouwen als een soort toezegging, dat wanneer de code loopt, deze door de werkelijke waarden vervangen wordt wanneer je deze benoemd. Ik doe dit met` my_player 80`. om noot 80 te spelen. Binnen de definitie van deze functie, is` n`nu vervangen door 80, dus` play n`verandert in` play 80`. Wanneer ik deze vernoem met` my_player 90´, is `n` nu vervangen met 90, play `n`is veranderd in play `90`.

Laten we eens kijken naar een interessanter voorbeeld:

    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

Hier gebruikte ik `repeats` als een cijfer in de regel `repeats.times do`.Ik gebruikte `root` ook als naam van een noot in mijn `play` oproep.

Hierbij zien we dat we in staat zijn om iets zeer expressief, maar makkelijk leesbaar te schrijven door onze logica in een functie te steken!