# Переменные

Присвоение имён полезно для вашего кода. С Sonic Pi это очень просто. Вы пишете желаемое имя, знак равенства, а затем то, что нужно запомнить:

    sample_name = :loop_amen

В этом примере мы “запомнили” обозначение `:loop_amen` в переменной `sample_name`. Теперь мы можем пользоваться `sample_name` везде, где мы могли бы указать `:loop_amen`. Например:

    sample_name = :loop_amen
    sample sample_name

Есть три главных причины для использования переменных в Sonic Pi: присвоение значения, управление повторами и захват результатов операций.

## Присвоение Значения

Когда вы пишете код, вы говорите компьютеру сделать что-то. Пока компьютер это понимает - всё в порядке. Но всё же важно помнить, что код читает не только компьютер. Другие люди, возможно, захотят тоже прочесть его и попробовать разобраться, что в нём происходит. Скорее всего и вы сами будете читать и пытаться понять свой собственный код в будущем. Сейчас всё кажется очевидным, но для остальных, или же для вас самих в будущем, это может быть не так!

Одним из способов помочь другим понять, что делает ваш код, - это оставлять комментарии (как мы это видели в предыдущей главе). Ещё один способ - давать осмысленные имена переменным. Посмотрите на этот код:

    sleep 1.7533

Зачем указано число `1.7533`? Откуда оно взялось? Что оно означает? Теперь взгляните на этот пример:

    loop_amen_duration = 1.7533
    sleep loop_amen_duration

Вот теперь стало ясно, что значит `1.7533`. Это же продолжительность сэмпла `:loop_amen`! Конечно, вы могли бы заметить, почему бы просто не написать так:

    sleep sample_duration(:loop_amen)

Это, безусловно, очень хороший способ выразить намерения кода.

## Управление Повторами

Часто вы видите много повторений в своем коде. Когда необходимо что-то поменять, то делать это приходится во многих местах. Посмотрите на следующее:

    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)

Много чего мы делаем с `:loop_amen`! Но что если мы захотим послушать как это будет звучать с другим замкнутым сэмплом, таким как `:loop_garzul`? Пришлось бы найти и заменить все `:loop_amen` на `:loop_garzul`. Этим можно заняться, если больше нечего делать. А как насчет живого выступления? Иногда время - это непозволительная роскошь. Особенно, если вы хотите, чтобы люди продолжали танцевать.

Ну, а если бы вы записали свой код так:

    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)

Он делает совершенно то же самое (попробуйте сами). Зато тут есть возможность заменить строку `sample_name = :loop_amen` на `sample_name = :loop_garzul`, что приведёт к реальным изменениям во многих местах. Вот что даёт нам магия переменных.

## Захват Результатов

Наконец, хороший повод использовать переменные - захватывать результат чего-либо. К примеру, вам может понадобится что-то сделать с продолжительностью сэмпла:

    sd = sample_duration(:loop_amen)

Теперь можно вставлять `sd` везде, где нам нужна длительность сэмпла `:loop_amen`.

Вероятно, ещё более важно то, что переменная разрешает нам сохранить результат вызова `play` или `sample`:

    s = play 50, release: 8

Мы захватили и запомнили `s` как переменную, которая позволяет управлять синтом, пока он играет:

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

В следующей главе мы рассмотрим подробнее управление синтами.

## Переменные

Whilst variables are great for giving things names and capturing the results of things, it is important to know that they should typically only be used locally within a thread. For example, don’t do this:

    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

In the above example we assign a ring of numbers to a variable `a` and then used it within two separate `live_loop`s. In the first live loop every `0.5`s we sort the ring (to `(ring 1, 2, 3, 4, 5, 6)`) and then print it out to the log. If you run the code, you’ll find that the printed list is not always sorted!. This may surprise you - especially that sometimes the list is printed as sorted, and sometimes it is not. This is called non-deterministic behaviour and is the result of a rather nasty problem called a race-condition. The problem is due to the fact that the second live loop is also manipulating the list (in this case shuffling it) and by the time the list is printed, sometimes it has just been sorted and sometimes it has just been shuffled. Both live loops are racing to do something different to the same variable and every time round a different loop ‘wins’.

There are two solutions to this. Firstly, don’t use the same variable in multiple live loops or threads. For example, the following code will always print a sorted list as each live loop has its own separate variable:

    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

However, sometimes we do want to share things across threads. For example, the current key, BPM, synth etc. In these cases, the solution is to use Sonic Pi’s special thread-safe state system via the fns `get` and `set`. This is discussed later on in section 10.