# Set и Get

Sonic PI имеет глобальное хранилище памяти, называемое Временным состоянием. В основном оно используется чтобы “установить” (set) информацию и “получить” (get) информацию. Давайте нырнем глубже…

## Set

Чтобы хранить информацию во Временном Состоянии нам нужны две вещи:

информация, которую мы хотим сохранить, уникальное имя (ключ) для этой информации.

Например, мы можем захотеть сохранить число `3000` с ключом `:intensity`. Это можно сделать используя функцию `set`:

    set :intensity, 3000

Мы можем дать ключу любое имя. Если какая-то информация уже хранится под этим именем, наш новый `set` перезапишет её:

    set :intensity, 1000
    set :intensity, 3000

В примере выше, где мы сохранили оба числа под одним ключом, последний вызов `set` ‘побеждает’, поэтому число связанное с `:intensity` будет равно `3000`, так как первый вызов ‘set’ эффективно перезаписан.

## Get

Для извлечения информации из Временного Состояния нам просто нужен ключ, который мы использовали в `set`, в нашем случае это `:intensity`. Тогда нам просто нужно вызвать `get[:intensity]`, результат которого выведем на экран:

    print get[:intensity] #=> выведет 3000

Обратите внимание, что запросы `get` могут возвращать информацию, которая была записана в `set` в предыдущем запуске исполнения кода. После того, как часть информации была записана в `set`, она становится доступной до тех пор, пока она либо не будет переопределена (точно так же, как мы переопределили значение`:intensity` от `1000` к ` 3000`), либо Sonic Pi не будет закрыт.

## Множество потоков выполнения

Основное преимущество системы Time State заключается в том, что ее можно безопасно использовать в потоках или в живых циклах. Например, у вас может быть сделана установка для одного живого цикла, а другой может ее получить:

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

Хорошая вещь об использовании `get` и`set` в потоках, подобных этому, заключается в том, что всегда будет выдаваться один и тот же результат всякий раз, когда вы запускаете исполнение кода. Попробуйте этом, и посмотрите, есть ли в вашем журнале следующее:

    {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

Попробуйте запустить этот код несколько раз - видите, результат одинаков каждый раз. Это то, что мы называем детерминированным поведением, и это действительно очень важно, когда мы хотим поделиться своей музыкой в виде кода и знать, что человек, играющий код, слышит именно то, что мы хотели, чтобы он услышал (точно так же, как воспроизведение MP3 или интернет-стрим звучат одинаково для всех слушателей).

## Просто о системе детерминированных состояний

В разделе 5.6 мы обсуждали, почему использование переменных в потоках может привести к случайному поведению. Это лишает нас возможности надежно воспроизводить код, такой как этот:

    ## Пример недетерминированного поведения
    ## (из-за гонки состояний, вызванной несколькими
    ## живыми циклами, манипулирующими одной и той же переменной
    ## в одно и то же время).
    ##
    ## Если вы запустите этот код, вы заметите
    ## что список, отображаемый в  журнале
    ## не всегда сортируется!
    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

Давайте посмотрим, как это может выглядеть, используя `get` и`set`:

    ## Пример детерминированного поведения
    ## (несмотря на одновременный доступ к общему состоянию)
    ## используя новую систему Time State от Sonic Pi.
    ##
    ## Когда этот код выполняется, список,
    ## отображаемый в журнале, всегда отсортирован!
    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

Обратите внимание, что этот код в значительной степени идентичен версии, использующей переменную. Однако когда вы запускаете код, он ведет себя так, как вы ожидаете с любым типичным кодом Sonic Pi - * он делает то же самое каждый раз * в этом случае благодаря системе Time State.

Поэтому, когда вы делитесь информацией между живыми циклами и потоками, используйте `get` и`set` вместо переменных для детерминированного, воспроизводимого поведения.