10.1 Set e Get

# Set e Get

O Sonic Pi tem um armazenamento global chamado de Time State. As duas coisas principais que fazes com ele é armazenar (`set`) informação e ler ( `get` ) informação. Vamos aprofundar...

## Set

Para armazenar informação no Time State são necessárias duas coisas:

1. a informação que queremos armazenar,
2. uma chave (nome único) para a informação.

Por exemplo, nós podemos querer armazenar o numero `3000` com a chave `:intensity`. Isto é possível utilizando a função `set` :

```
set :intensity, 3000
```

Podemos usar qualquer nome para a nossa chave. Se alguma informação já foi armazenada anteriormente com a mesma chave, o nosso novo `set` vai substitui-la:

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

No exemplo em cima, nós guardamos ambos os números utilizando a mesma chave, a ultima chamada `set` ganha , por isso o numero associado a `:intensity` vai ser `3000` já que a primeira chamada ao `set` é efetivamente substituída.

## Get

Para tirar informação do Time State só precisamos de utilizar a chave que utilizamos para armazena-la (`set`) , que no nosso caso e `:intensity`. Só precisamos então de chamar `get[:intensity]`que podemos ver ao imprimirmos o resultado para o log:

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

Notice that calls to `get` can return information that was `set` in a previous run. Once a piece of information has been `set` it is available until either the information is overridden (just like we clobbered the `:intensity` value of `1000` to `3000` above) or Sonic Pi is closed.

## Várias Threads

The main benefit of the Time State system is that it can be safely used across threads or live loops. For example, you could have one live loop setting information and another one getting it:

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

The nice thing about using `get` and `set` across threads like this is that it will always produce the same result every time you hit run. Go on, try it. See if you get the following in your log:

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

Try running it a few times - see, it's the same every time. This is what we call deterministic behaviour and it's really very important when we want to share our music as code and know that the person playing the code is hearing exactly what we wanted them to hear (just like playing an MP3 or internet stream sounds the same for all listeners).

## A Simple Deterministic State System

Atrás na secção 5.6 discutimos a razão pela qual utilizar variáveis através de diferentes threads pode levar a comportamento aleatório. Isto faz-nos desconfiar de código como este:

```
## Um exemplo de comportamento não-determinístico
## (devido a race conditions causadas por múltiplos
## loops manipulando a mesma variárvel ao mesmo tempo).
##  
## Se você executar este código você notará
## que a lista que é impressa
## nem sempre sai ordenada!
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
```

Let's take a look at how this might look using `get` and `set`:

```
## Um exemplo de comportamento determinístico
## (apesar do acesso simultâneo ao estado compartilhado)
## usando o novo sistema Time State do Sonic Pi.
##
## Quando este código é executado, a lista
## sempre é impressa de forma ordenada!
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
```

Notice how this code is pretty much identical to the version using a variable before it. However when you run the code, it behaves as you would expect with any typical Sonic Pi code - *it does the same thing every time* in this case thanks to the Time State system.

Therefore, when sharing information across live loops and threads, use `get` and `set` instead of variables for deterministic, reproducible behaviour.
