5.6 Variáveis

# Variáveis

Uma coisa útil a fazer no nosso código é dar nomes às coisas. Sonic Pi torna isto muito fácil: escreves o nome que queres usar, um sinal de igual (`=`), e a coisa que te queres lembrar:

```
sample_name = :loop_amen
```

Aqui "lembramo-nos" do símbolo `:loop_amen`na variável `sample_name`. Podemos agora usar `sample_name`em todo o lado que usaríamos `:loop_amen`. Por exemplo:

```
sample_name = :loop_amen
sample sample_name
```

Existem 3 razões principais para usar variáveis no Sonic Pi: comunicar significado, gerir repetições e capturar o resultado de coisas.

## Comunicar sentido

Quando escreves código é fácil de pensar que estas a dizer ao computador como fazer coisas - desde que o computador perceba está Ok. No entanto é importante lembrar que não é só o computador que lê código. Outras pessoas podem o ler e tentar perceber o que se está a passar. Além disso, é provável que tenhas que ler o teu código no futuro e tentar perceber o que se passa. Apesar de poder parecer óbvio para ti agora - pode não o ser para outros ou o teu eu futuro!

Uma maneira de ajudar os outros a perceber o que o teu código está a fazer é adicionar comentários (como vimos na secção anterior). Outra coisa é usar nomes de variáveis com sentido. Vê este código:

```
sleep 1.7533
```

Porque usa o numero `1.7533`? De onde veio este número? O que significa? Vê agora este código:

```
loop_amen_duration = 1.7533
sleep loop_amen_duration
```

Agora é muito mais claro o que `1.7533`significa: é a duração do sample `:loop_amen`! Claro, podes dizer porque não escrever simplesmente:

```
sleep sample_duration(:loop_amen)
```

Que, claro, é uma boa maneira de comunicar a intenção do código.

## Gerindo a repetição

Frequentemente vês muita repetição no teu código e quando queres mudar as coisas, tens que as mudar em muitos sítios. Vê este código:

```
sample :loop_amen
sleep sample_duration(:loop_amen)
sample :loop_amen, rate: 0.5
sleep sample_duration(:loop_amen, rate: 0.5)
sample :loop_amen
sleep sample_duration(:loop_amen)
```

Estamos a fazer muitas coisas com o `:loop_amen`! E se queremos ouvir como soa com outro loop sample como o `:loop_garzul`? Teremos de encontrar e substituir todos os `:loop_amen`s por `:loop_garzul`. Isso pode ser Ok se tiveres muito tempo - mas se tiveres a actuar em palco? As vezes não temos o luxo de tempo - especialmente se queres manter as pessoas a dançar.

E se escreveres código como este:

```
sample_name = :loop_amen
sample sample_name
sleep sample_duration(sample_name)
sample sample_name, rate: 0.5
sleep sample_duration(sample_name, rate: 0.5)
sample sample_name
sleep sample_duration(sample_name)
```

Isto faz exactamente o mesmo que o anterior (experimenta). Também nos dá a habilidade de apenas mudar uma linha `sample_name = :loop_amen` para `sample_name = :loop_garzul`e mudamos em muitos sítios pela magia das variáveis.

## Capturando resultados

Finalmente, uma boa motivação para usar variáveis é para capturar o resultados de coisas, podes querer fazer coisas com a duração do sample:

```
sd = sample_duration(:loop_amen)
```

Agora podemos usar `sd` em qualquer lugar que necessitemos da duração do sample `:loop_amen`.

Talvez mais importante, a variável permite nos capturar o resultado da chamada a `play`ou a `sample`:

```
s = play 50, release: 8
```

Agora capturamos e lembramos-nos de `s` como variável, que nos permite controlar o synth enquanto corre:

```
s = play 50, release: 8
sleep 2
control s, note: 62
```

Veremos como controlar os synths em mais detalhe numa secção posterior.


## Aviso: Variáveis and Threads

Embora as variáveis sejam ótimas para dar nomes às coisas e capturar os resultados das coisas, é importante saber que elas normalmente só devem ser usadas localmente num segmento. Por exemplo, *não faça isso*:

```
a = (ring 6, 5, 4, 3, 2, 1)
live_loop :sorted do
  a = a.sort
  sleep 0.5
  puts "sorted: ", a
end
live_loop :shuffled do
  a = a.shuffle
  sleep 0.5
end
```

No exemplo acima, atribuímos um anel de números a uma variável 'a' e usamo-lo dentro de dois ciclos "live_loop" separados. No primeiro ciclo "live_loop" a cada 0.5 segundos nós ordenamos o anel (para `(anel 1, 2, 3, 4, 5, 6)`) e imprimimos no log. Se executares o código, verás que a lista impressa * nem sempre é ordenada! *. Isto pode surpreender-te - especialmente porque às vezes a lista é impressa ordenada e outras vezes não. Isto é chamado de comportamento não determinístico e é o resultado de um problema bastante desagradável chamado de condição de corrida. O problema deve-se ao fato de que o segundo ciclo "live_loop" também manipular a lista (neste caso, embaralhando-a) e no momento em que a lista é impressa, às vezes ela acaba de ser ordenada e outras vezes acaba de ser embaralhada. Ambos os ciclos "live_loop" estão concorrendo para fazer algo diferente na mesma variável e em cada vez um ciclo diferente 'ganha'.

Existem duas soluções para isto. Primeiro, *não usar as mesmas variáveis em múltiplos ciclos "live_loop" ou threads*. Por exemplo, o seguinte código  deverá sempre imprimir uma lista ordenada à medida que cada ciclo "live_loop" tenha as suas variáveis separadas

```
live_loop :shuffled do
 a = (ring 6, 5, 4, 3, 2, 1)
 a = a.shuffle 
sleep 0.5
end
live_loop :sorted do 
a = (ring 6, 5, 4, 3, 2, 1)
a = a.sort
sleep 0.5
puts "sorted: ", a
end
```

No entanto, ás vezes queremos partilhar coisas entre threads. Por exemplo, a tecla atual, as BPM, sintetizador, etc. Nestes casos, a solução é o utilizar as funções `get` e`set` que fazem parte do sistema seguro do Sonic PI para partilha entre threads.
