5.5 Fonctions

# Fonctions

Une fois que vous commencez à écrire beaucoup de code, vous pouvez 
souhaiter trouver le moyen d'organiser et de structurer les choses pour 
les rendre plus ordonnées et faciles à comprendre. Les fonctions sont 
un moyen très puissant pour le faire. Elles vous donnent la capacité de 
donner un nom à un morceau de code. Jetons-y un œil.

## Definition des fonctions

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

Ici, nous avons défini une nouvelle fonction appelée `foo`. Nous 
faisons cela avec notre vieil ami, le bloc do/end et le mot magique 
`define` suivi par le nom que nous voulons donner à notre fonction. 
Nous ne sommes pas tenus de l'appeler `foo`, nous aurions pu l'appeler 
avec n'importe quel nom que nous voulions, comme `bar`, `baz` ou 
idéalement quelque chose de significatif pour vous comme 
`section_principale` ou `lead_riff`.

Rappelez-vous d'ajouter un deux-points `:` devant le nom de votre 
fonction quand vous la définissez.

## Appel des fonctions

Une fois que nous avons défini notre fonction, nous pouvons l'appeler 
simplement en écrivant son nom :

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

foo

sleep 1

2.times do
  foo
end
```

Nous pouvons même utiliser `foo` à l'intérieur de blocs d'itération 
ou n'importe où nous aurions pu écrire `play` ou `sample`. Ceci nous 
donne un super moyen de nous exprimer et de créér de nouveaux mots 
significatifs à utiliser dans nos compositions.

## Les fonctions sont mémorisées à travers des runs

Pour le moment, chaque fois que nous avons pressé le bouton Run, Sonic 
Pi a démarré d'un état complètement vierge. Il ne savait rien à part ce 
qui était dans le buffer. Vous ne pouviez pas référencer du 
code d'un autre buffer ou d'un autre thread. Toutefois, les 
fonctions changent cela. Quand vous définissez une fonction, Sonic Pi 
s'en *rappelle*. Essayons-le. Effacez tout le code dans votre buffer et 
remplacez-le par :

```
foo
```

Pressez le bouton Run et écoutez votre fonction qui est jouée. Où le 
code est-il allé ? Comment Sonic Pi sait-il quoi jouer ? Sonic Pi s'est 
simplement souvenu de votre fonction - ainsi, même après l'avoir 
effacée de votre buffer, il se rappelle de ce que vous avez 
tapé. Ce comportement fonctionne uniquement avec les fonctions créées 
en utilisant `define` (et `defonce`).

## Fonctions paramétrées

Vous pourriez être intéressé à savoir que juste comme vous pouvez 
passer les valeurs min et max à `rrand`, vous pouvez apprendre à vos 
fonctions à accepter des arguments. Jetons-y un œil.

```
define :my_player do |n|
  play n
end

my_player 80
sleep 0.5
my_player 90
```

Ce n'est pas très excitant, mais ça illustre le point. Nous avons 
créé notre propre version de `play` appelée `my_player` et qui est 
paramétrée.

Les paramètres doivent être placés après le `do` du bloc do/end de 
`define`, entourés par des barres verticales `|` et séparés par des 
virgules `,`. Vous pouvez utiliser tout mot que vous souhaitez pour les 
noms de paramètres. 

La magie se passe à l'intérieur du bloc do/end de `define`. Vous 
pouvez utiliser les noms de paramètres comme si c'étaient des valeurs 
réelles. Dans cet exemple, je joue la note `n`. Vous pouvez considérer 
les paramètres comme une sorte de promesse qui fait que, lorsque le code 
s'exécute, ils sont remplacés par des valeurs réelles. Vous faites 
ceci en passant un argument à la fonction quand vous l'appelez. Je le 
fais avec `my_player 80` pour jouer la note 80. À l'intérieur de la 
définition de la fonction, `n` est alors remplacé par 80, donc 
`play n` est changé en `play 80`. Quand je l'appelle une nouvelle fois 
avec `my_player 90`, `n` est alors remplacé par 90, donc `play n` est 
changé en `play 90`.

Voyons un exemple plus intéressant :

``` 
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

```

Ici j'ai utilisé `repeats` comme si c'était un nombre dans la ligne 
`repeats.times do`. J'ai aussi utilisé `root` comme si c'était un nom de 
note dans mon appel à `play`.

Voyez comme nous sommes capables d'écrire quelque chose de très 
expressif et facile à lire en déplaçant beaucoup de notre logique à 
l'intérieur d'une fonction !
