# Set i Get

Sonic Pi posiada globalny magazyn pamięci nazywany Stanem Czasu. Dwie podstawowe operacje jakie możesz na nim wykonywać to ustawienie informacji (`set`) oraz pobranie informacji (`get`). Zanurzmy się głębiej…

## Set

Aby dodać jakąś informację do Stanu Czasu musimy zrobić dwie rzeczy:

1. informacja, którą zamierzamy dodać,
2. unikalna nazwa (klucz) dla naszej informacji.

Na przykład, możemy chcieć zachować liczbę `3000` pod kluczem `:intensity` (intensywność). Można to zrobić używając funkcji `set`:

    set :intensity, 3000

Możemy użyć dowolnej nazwy dla naszego klucza (key). Jeśli jakaś informacja została już zapisana pod tym kluczem, nasze nowe ustawienie (`set`) nadpisze je:

    set :intensity, 1000
    set :intensity, 3000

W powyższym przykładzie, jako że zapisaliśmy obie liczby pod tym samym kluczem, ostanie uruchomienie funkcji `set` ‘wygrywa’. Wynika z tego, że liczba powiązana z `:intensity` będzie wynosić `3000` ponieważ pierwsze wywołanie funkcji `set` zostało efektywnie nadpisane.

## Pobierz (Get)

Aby pobrać informację ze Stanu Czasu (Time State) potrzebujemy tylko klucza, którego użyliśmy do ustawienia go za pomocą funkcji `set`, w naszym przypadku jest to `:intensity` Następnie musimy tylko uruchomić polecenie `get[:intensity]` i będziemy mogli podejrzeć tę wartość poprzez wyświetlenie wyniku w panelu z logami:

    print get[:intensity] #=> prints 3000

Zauważ, że odwołanie do `get` może zwrócić informację która została ustawiona (`set`) w poprzednim uruchomieniu. Gdy już raz pewna informacja zostanie ustawiona za pomocą polecenia `set` staje się ona dostępna dopóki nie zostanie nadpisana (dokładnie tak samo jak zmieniliśmy wartość dostępną pod symbolem`:intensity`z `1000` na `3000` powyżej) lub Sonic PI zostanie zamknięty.

## Wiele Wątków

Podstawową korzyścią systemu Stanu Czasu (Time State) jest to, że może być on bezpiecznie używany pomiędzy różnymi wątkami oraz żywymi pętlami. Na przykład, możesz mieć jedną żywą pętlę, która ustawia pewną informację oraz inną, która ją wyciąga:

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

Ogromną zaletą korzystania z funkcji `set` i `get` w różnych wątkach jest fakt, że zawsze dają one ten sam wynik przy uruchomieniu przycisku ‘Run’. Dalej, spróbuj sam. Sprawdź czy dostaniesz taki sam rezultat w swoich logach:

    {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

Spróbuj uruchomić to kilkukrotnie - zauważ, że za każdym razem wynik jest taki sam. To jest właśnie coś co nazywamy zachowaniem deterministycznym. Jest to bardzo ważne gdy chcemy podzielić się naszą muzyką jako kodem. Zależy nam na tym aby osoba uruchamiająca nasz kod usłyszała dokładnie to co chcieliśmy aby usłyszała (dokładnie tak samo jak z odtworzeniem utworu MP3 czy stream’a z dźwiękiem w internecie brzmi identycznie dla każdego ze słuchaczy).

## Prosty Deterministyczny System Stanu

Wcześniej w Sekcji 5.6 rozważaliśmy dlaczego wykorzystywanie zmiennych w różnych wątkach może prowadzić do nieoczekiwanych zachowań. Powoduje to, że nie jesteśmy w stanie wiarygodnie odtworzyć kod taki jak ten:

    ## 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

Spróbujmy zobaczyć jak mogłoby to wyglądać gdybyśmy użyli funkcji `get` i `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

Zauważ, że ten kod jest prawie identyczny z wersją, w której używaliśmy wcześniej zmiennej. Jednakże, kiedy uruchomisz ten kod, zacznie się on zachowywać tak jakbyś tego oczekiwał od typowego kodu Sonic Pi - w tym wypadku za każdym razem jest wykonywana ta sama rzecz, wszystko dzięki systemowi Stanu Czasu (Time State).

Dlatego, gdy współdzielimy informację pomiędzy różnymi żywymi pętlami i wątkami, używajmy funkcji `get` i `set` zamiast zmiennych aby otrzymać deterministyczne i powtarzalne zachowanie.