8.5 Cadenas de Anillos

# Cadenas de Anillos

Otra forma de crear nuevos anillos, además de con constructores como `range` y `spread`, es manipulando anillos existentes.


## Comandos de Cadenas

Para explorar esta idea, mira el siguiente anillo:

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

¿Y si lo queremos de atrás a delante? Bueno, sólo tendríamos que usar el comando `.reverse` para coger el anillo y darle la vuelta:

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

Ahora bien, ¿y si queremos los tres primeros valores del anillo?

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

Finalmente, ¿y si queremos mezclar (barajar) el anillo?

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

## Cadenas Múltiples

Por sí sola, ésta es una forma muy potente de crear nuevos anillos. Sin embargo, el *verdadero* poder viene cuando encadenas unos cuantos de estos comandos juntos.

¿Y qué me dices de desordenar el anillo, quitarle 1 elemento, y después coger los siguientes 3?

Veamos esto por pasos:

1. `(ring 10, 20, 30, 40, 50)` - nuestro anillo inicial
2. `(ring 10, 20, 30, 40, 50).shuffle` - lo desordenamos - `(ring 40, 30, 10, 50, 20)`
3. `(ring 10, 20, 30, 40, 50).shuffle.drop(1)` - quitamos 1 - `(ring 30, 10, 50, 20)`
4. `(ring 10, 20, 30, 40, 50).shuffle.drop(1).take(3)` - cogemos 3 - `(ring 30, 10, 50)`

¿Ves cómo hemos creado una cadena larga de estos métodos con sólo *unirlos*? Podemos combinarlos en el orden que queramos; ésta es una forma extremadamente rica y potente de generar nuevos anillos a partir de anillos existentes.

## Inmutabilidad

Estos anillos tienen una propiedad muy poderosa e importante. Son inmutables, es decir, no pueden cambiar. Esto significa que la cadena de métodos descrita en esta sección *no cambia anillos*, sino que *crea nuevos anillos*. Por eso, puedes compartir anillos entre distintos hilos con total libertad; puedes encadenarlos dentro de un hilo sabiendo que ningún otro hilo usando el mismo anillo se va a ver afectado.

## Métodos de Cadenas Disponibles

Aquí tienes una lista de los métodos de cadenas disponibles, para que juegues con ellos:

* `.reverse` - devuelve una versión del anillo dado la vuelta
* `.sort` - crea una versión ordenada del anillo
* `.shuffle` - crea una versión desordenada del anillo
* `.pick(3)` - devuelve un anillo que es el resultado de llamar `.choose` 3 veces
* `.pick(3)` - devuelve un anillo que es el resultado de llamar `.choose` 3 veces
* `.take(5)` - devuelve un anillo nuevo, que sólo contiene los primeros 5 elementos
* `.drop(3)` - devuelve un anillo nuevo con todos los elementos salvo los 3 primeros
* `.butlast` - devuelve un anillo nuevo sin el último elemento
* `.drop_last(3)` - devuelve un nuevo anillo sin los 3 últimos elementos
* `.take_last(6)`- devuelve un anillo nuevo con sólo los últimos 6 elementos
* `.stretch(2)` - repite cada elemento en el anillo dos veces
* `.repeat(3)` - repite el anillo entero 3 veces
* `.mirror` - añade el anillo a una versión invertida del mismo
* `.reflect` - lo mismo que mirror, pero no duplica el valor del medio
* `.scale(2)` - devuelve un anillo nuevo con todos los elementos multiplicados por 2 (asume que el anillo sólo contiene números)

Por supuesto, estos métodos para cadenas con números, ¡pueden utilizar otros números cualquiera! Así que, siéntete libre de llamar `.drop(5)` en vez de `.drop(3)` si quieres quitar los primeros 5 elementos.
