# Zmienne

Przydatną rzeczą, którą możesz robić w swoim kodzie, to tworzenie nazw dla różnych rzeczy. Sonic Pi sprawia, że jest to bardzo łatwe - wpisujesz wybraną przez siebie nazwę, znak równości (`=`), a następnie rzecz do zapamiętania:

    sample_name = :loop_amen

W powyższym kawałku kodu ‘zapisaliśmy’ wartość symbolu `:loop_amen` w zmiennej `sample_name`. Od teraz możemy używać nazwy `sample_name` wszędzie, gdzie do tej pory użylibyśmy sampla `:loop_amen`. Na przykład:

    sample_name = :loop_amen
    sample sample_name

Są trzy podstawowe powody na korzystanie ze zmiennych w Sonic Pi: komunikowanie znaczenia, zarządzanie powtórzeniami oraz przechwytywanie wyników różnych rzeczy.

## Komunikowanie Znaczenia

Kiedy piszesz kod, łatwo jest myśleć, że jedyne, co robisz, to mówisz komputerowi, jak ma wykonać jakieś rzeczy - tak długo, jak on rozumie, co do niego mówisz, to jest w porządku. Jednakże ważne jest, aby pamiętać, że nie tylko komputer czyta kod. Inni ludzie również mogą chcieć przeczytać go i spróbować zrozumieć, co się w nim dzieje. Ponadto bardzo prawdopodobne, że Ty również będziesz czytał swój własny kod w przyszłości i próbował zrozumieć, o co w nim chodzi. Chociaż w tej chwili jego znaczenie może być dla Ciebie oczywiste - może nie być takie oczywiste dla innych lub nawet dla Ciebie samego w przyszłości!

Jedną z metod, która pomoże innym zrozumieć, co Twój kod robi, jest pisanie komentarzy (co widzieliśmy już we wcześniejszej sekcji tego samouczka). Inną jest używanie takich nazw dla zmiennych, które coś znaczą. Spójrz na poniższy kod:

    sleep 1.7533

Dlaczego używa on liczby `1.7533`? Skąd wzięła się ta liczba? Co ona oznacza? A teraz spójrz na poniższy kod:

    loop_amen_duration = 1.7533
    sleep loop_amen_duration

Teraz zrozumienie tego, co oznacza liczba `1.7533`, jest znacznie prostsze: oznacza ona długość trwania sampla `:loop_amen`! Oczywiście możesz zapytać, dlaczego po prostu nie napisaliśmy:

    sleep sample_duration(:loop_amen)

Co jak najbardziej jest bardzo fajnym sposobem zakomunikowania intencji zawartych w kodzie.

## Zarządzanie Powtórzeniami

Często widzisz dużo powtórzeń w Twoim kodzie i kiedy chcesz coś zmienić, musisz wprowadzić zmiany w wielu miejscach. Spójrz na poniższy kawałek kodu:

    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)

Robiliśmy tutaj sporo rzeczy z samplem `:loop_amen`! Co, jeśli chcielibyśmy usłyszeć, jak ten kawałek kodu brzmi z innym samplem, na przykład `:loop_garzul`? Musielibyśmy wtedy znaleźć i zamienić wszystkie wystąpienia sampla `:loop_amen` na `:loop_garzul`. To może być całkiem w porządku, jeśli masz sporo luzu - ale co, gdy właśnie występujesz na scenie? Czasami nie masz tego luksusu, że masz czasu tyle, ile chcesz - zwłaszcza wtedy, gdy chcesz utrzymać ludzi na parkiecie.

A co, jeśli powyższy kawałek kodu przepiszemy na coś takiego?:

    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)

Teraz ten kod robi dokładnie to samo, co wcześniejszy (spróbuj). Oprócz tego daje nam możliwość zmiany tylko jednej linijki z obecnej `sample_name = :loop_amen` na `sample_name = :loop_garzul`, aby jednocześnie zmienić brzmienie w wielu miejscach dzięki magii zmiennych.

## Przechwytywanie Wyników

I na koniec dobrym powodem do używania zmiennych jest przechwytywanie wyniku wykonania różnych rzeczy. Przykładowo możesz chcieć robić różne rzeczy z długością trwania sampla:

    sd = sample_duration(:loop_amen)

Możemy teraz używać zmiennej `sd` wszędzie tam, gdzie potrzebujemy użyć długości trwania sampla `:loop_amen`.

Możliwe, że nawet bardziej ważne jest to, iż zmienne pozwalają nam na przechwycenie i zapisanie wyniku uruchomienia polecenia `play` lub `sample`:

    s = play 50, release: 8

Teraz złapaliśmy i zapamiętaliśmy `s` jako zmienną, co pozwala nam na kontrolę syntezatora w trakcie jego działania:

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

Przyjrzymy się bardziej kontrolowaniu syntezatorów w kolejnej sekcji.

## Zmienne

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.