10.1 Set y Get

# Set y Get

Sonic Pi tiene un almacén de memoria global llamado Time State. Las dos cosas principales que se hacen con él son `set` (establecer) información y `get` (obtener) información. Vamos a profundizar...

## Set

Para almacenar información en el Time State necesitamos dos cosas:

1. los datos que queremos almacenar,
2. un nombre único (clave) para los datos.

Por ejemplo, puede ser que queremos almacenar el número `3000` con la clave `:intensity`. Eso es posible utilizando la función `set`:

```
set :intensity, 3000
```

Podemos utilizar cualquier nombre para nuestra clave. Si esta clave ya tiene datos almacenados, nuestro nuevo `set` tendrá primacía:

```
set :intensity, 1000
set :intensity, 3000
```

En el ejemplo anterior, como almacenamos ambos números bajo la misma clave, la última llamada a `set` 'gana', por lo que el número asociado a `:intensidad` será `3000` ya que la primera llamada a `set` es efectivamente anulada.

## Get

Para obtener la información del Time State sólo necesitamos la clave que utilizamos para `set` (establecerlo), que en nuestro caso es `:intensity`. Entonces sólo tenemos que llamar a `get[:intensity]` que podemos ver imprimiendo el resultado en el registro:

```
print get[:intensity] #=> imprime 3000
```

Observa que las llamadas a `get` pueden devolver información que fue `set` en una ejecución anterior. Una vez que una pieza de información ha sido "fijada", está disponible hasta que la información sea sobrescrita (al igual que el valor de `:intensity` de `1000` a `3000`) o Sonic Pi se cierra.

## Hilos

La principal ventaja del sistema Time State es que puede utilizarse de forma segura entre hilos o bucles vivos. Por ejemplo, puedes tener un bucle vivo estableciendo información y otro obteniéndola:

```
live_loop :setter do
  set :foo, rrand(70, 130)
  sleep 1
end
live_loop :getter do
  puts get[:foo]
  sleep 0.5
end
```

Lo bueno de usar `get` y `set` entre hilos de esta manera es que siempre va a producir el mismo resultado cada vez que ejecutas el código. Adelante, intentalo. Verás lo siguiente en tu bitácora:

```
{run: 0, time: 0.0}
 └─ 125.72265625
{run: 0, time: 0.5}
 └─ 125.72265625
{run: 0, time: 1.0}
 └─ 76.26220703125
{run: 0, time: 1.5}
 └─ 76.26220703125
{run: 0, time: 2.0}
 └─ 114.93408203125
{run: 0, time: 2.5}
 └─ 114.93408203125
{run: 0, time: 3.0}
 └─ 75.6048583984375
{run: 0, time: 3.5}
 └─ 75.6048583984375
```

Intenta correrlo unas cuantas veces - ¿Lo ves? Es el mismo resultado cada vez. Esto es lo que llamamos comportamiento determinista y es bastante importante cuando compartimos nuesta música como código y saber que la persona que está ejecutando el código está escuchando exactamente lo que quisimos que escuchara (justo como cuando reproducimos un MP3 o una transmisión por internet, todos los oyentes escuchan lo mismo).

## Un Sistema de Estados Determinista Simple

Ya en la Sección 5.6 discutimos por qué el uso de variables entre hilos puede conducir a un comportamiento aleatorio. Esto nos impide poder reproducir de manera fiable un código como este:

```
## An Example of Non-Deterministic Behaviour
## (due to race conditions caused by multiple
## live loops manipulating the same variable
## at the same time).
##  
## If you run this code you'll notice
## that the list that's printed is
## not always sorted!
a = (ring 6, 5, 4, 3, 2, 1)
live_loop :shuffled do
  a = a.shuffle
  sleep 0.5
end
live_loop :sorted do
  a = a.sort
  sleep 0.5
  puts "sorted: ", a
end
```

Echemos un vistazo a cómo se vería esto usando `get` y` set`:

```
## An Example of Deterministic Behaviour
## (despite concurrent access of shared state)
## using Sonic Pi's new Time State system.
##
## When this code is executed, the list that's
## printed is always sorted!
set :a, (ring 6, 5, 4, 3, 2, 1)
live_loop :shuffled do
  set :a, get[:a].shuffle
  sleep 0.5
end
live_loop :sorted do
  set :a, get[:a].sort
  sleep 0.5
  puts "sorted: ", get[:a]
end
```

Nota como este código es casi identico a la versión donde se utiliza una variable antes de. Sin embargo cuando corres el código, se comporta como esperarías de cualquier código típico de Sonic Pi -*hace exactamente lo mismo cada vez*- en este caso gracias al sistema de Time State.

Siendo así, cuando compartimos información entre live loops e hilos, es preferible usar `get` y `set` en vez de variables para un comportamiento determinista y reproducible.
