8.5 Chaînes d'anneaux

# Chaînes d'anneaux

En plus des constructeurs comme `range` et `spread`, une autre façon de créer de nouveaux anneaux est de manipuler des anneaux existants.


## Commandes de chaîne

Pour explorer ceci, prenons un anneau simple :

```
(ring 10, 20, 30, 40, 50)
```

Et si on voulait son inverse ? Eh bien on utiliserait la commande de chaîne `.reverse` pour prendre l'anneau et l'inverser :

```
(ring 10, 20, 30, 40, 50).reverse  #=> (ring 50, 40, 30, 20, 10)
```

Et si on voulait les trois premières valeurs de l'anneau ?

```
(ring 10, 20, 30, 40, 50).take(3)  #=> (ring 10, 20, 30)
```

Finalement, et si on voulait mélanger l'anneau ?

```
(ring 10, 20, 30, 40, 50).shuffle  #=> (ring 40, 30, 10, 50, 20)
```

## Chaînes multiples

C'est déjà une manière puissante de créer de nouveaux anneaux. Ceci dit la *vraie* puissance vient quand on enchaîne quelques-unes de ces commandes à la suite.

Et si on mélangeait l'anneau, on lâchait un élément puis on en prenait les trois suivants ?

Regardons ceci par étapes :

1. `(ring 10, 20, 30, 40, 50)` - notre anneau initial
2. `(ring 10, 20, 30, 40, 50).shuffle` - mélange - `(ring 40, 30, 10, 50, 20)`
3. `(ring 10, 20, 30, 40, 50).shuffle.drop(1)` - en lâche un - `(ring 30, 10, 50, 20)`
4. `(ring 10, 20, 30, 40, 50).shuffle.drop(1).take(3)` - en prend trois - `(ring 30, 10, 50)`

Vous voyez comme on peut créer une longue chaîne de ces méthodes juste *en les collant à la suite*. On peut les combiner dans l'ordre qu'on veut, ce qui crée une manière extrêmement riche et puissante de générer de nouveaux anneaux à partir d'anneaux existants.

## Immutabilité

Ces anneaux ont une propriété puissante et importante. Ils sont immutables, ce qui veut dire qu'ils ne peuvent pas changer. Cela veut dire que les méthodes de chaînage décrites dans cette section *ne modifient pas les anneaux*, elles *en créent plutôt de nouveaux*. Cela veut dire que vous êtes libres de partager des anneaux entre les threads et de les chaîner dans un thread en sachant que vous n'affecterez aucun autre thread qui utilise le même anneau.

## Méthodes de chaîne disponibles

Voici une liste des méthodes de chaîne disponibles :

* `.reverse` - retourne une version inversée de l'anneau
* `.sort` - crée une version triée de l'anneau
* `.shuffle` - crée une version mélangée de l'anneau
* `.pick` - retourne un anneau avec le résultat d'un appel à `.choose` une fois
* `.pick(3)` - retourne un anneau avec le résultat de trois appels à `.choose`
* `.take(5)` - retourne un nouvel anneau contenant uniquement les cinq premiers éléments
* `.drop(3)` - retourne un nouvel anneau avec tout sauf les trois premiers éléments
* `.butlast` - retourne un nouvel anneau sans le dernier élément
* `.drop_last(3)` - retourne un nouvel anneau sans les trois derniers éléments
* `.take_last(6)`- retourne un nouvel anneau avec les six derniers éléments seulement
* `.stretch(2)` - répète chaque élément dans l'anneau deux fois
* `.repeat(3)` - répète l'anneau entier trois fois
* `.mirror` - ajoute l'anneau à une version inversée de lui-même
* `.reflect` - comme `.mirror` mais sans dupliquer la valeur du milieu
* `.scale(2)` - retourne un nouvel anneau avec tous les éléments multipliés par 2 (l'anneau doit contenir uniquement des nombres)

Évidemment, les méthodes de chaîne qui prennent des nombres peuvent prendre d'autres nombres aussi ! N'hésitez donc pas à appeler `.drop(5)` au lieu de `.drop(3)` si vous voulez lâcher les cinq premiers éléments.
