# Set en get

Sonic Pi heeft een globaal memory model genaamd tijd toestand. De twee belangrijkste dingen die je ermee doet is informattie `zetten` (set) en `ophalen` (get). Laten we erin duiken…

## Set

Om informatie op te slaan in de tijd toestand hebben we twee dingen nodig:

de informatie die we willen opslaan, een unieke naam (sleutel) voor de informatie.

We willen bijvoorbeeld het getal `3000` opslaan met de sleutel `:intensiteit`. Dit is mogelijk door de `set` functie te gebruiken:

    set :intensiteit, 3000

We kunnen elke naam gebruiken voor onze sleutel. Wanneer informatie al was opgeslagen voor die sleutel, dan overschrijft de nieuwe `set` die:

    set :intensiteit, 1000
    set :intensiteit, 3000

In het bovenstaande voorbeeld hebben we beide getallen opgeslagen onder dezelfde sleutel. De laatste aanroep van `set` ‘wint’. Het getal dat gekoppeld is aan `:intensiteit` zal `3000` zijn omdat de eerste aanroep van `set` effectief wordt overschreven.

## Get

Om informatie op te halen uit de tijd toestand hebben we allen de sleuten nodig die werd gebruikt om voor `set`. In ons geval is dat `:intensiteit`. We hoeven alleen `get[:intensiteit]` aan te roepen wat we kunnen zien door het resultaat naar het log af te drukken:

    print get[:intensiteit] #=> print 3000

Merk op dat aanroepen van `get` informatie kunnen teruggeven die was ge`set` in de vorige uitvoering. Wanneer een stuk informatie is ge`set` is het beschikbaar totdat of de informatie is overschreven (net als de aanpassing van `:intensiteit` van de waarde `1000` naar `3000` hierboven) of Sonic Pi is afgesloten.

## Meerdere threads

Het belangrijkste voordeel van het tijd toestand systeem is dat het veilig gebruikt kan worden tussen meerdere threads of live lussen. Je kunt bijvoorbeeld een live lus hebben voor het zetten van informatie en een andere voor het ophalen:

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

Het leuke aan het gebruik van `get` en `set` tussen meerdere threads zoals hier is dat het altijd hetzelfde resultaat oplevert iedere keer dat je op uitvoeren drukt. Vooruit, probeer het. Kijk op je het volgende in je log krijgt:

    {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

Probeer het een paar keer uit te voeren, zie je wel, het is steeds hetzelfde. Dit is wat we deterministisch gerag noemen en het is werkelijk heel belangrijk wanneer we onze muziek als code willen delen en zeker willen weten dat de persoon die code afspeelt exact hetzelfde hoort als wat we wilden dat ze hoorden (net als een MP3 afpselen of een internet stream voor alle luisteraars hezelfde klinkt).

## Een simple deterministisch toestandssysteem

Eerder, in sectie 5.6, bespraken we waarom variabelen gebruiken over meerdere threads voor willekeurig gedrag kan zorgen. Daardoor is het betrouwbaar reproduceren zoals de volgende code niet mogelijk:

    ## Een voorbeeld van niet deterministisch gedrag
    ## (veroorzaakt door race condities veroorzaakt door meerdere
    ## live lussen die dezelfde variable manipuleren
    ## op hetzelfde moment).
    ##
    ## Wanneer je deze code uitvoert zul je opmerken
    ## dat de lijst die wordt afgedrukt
    ## niet altijd gesorteerd is
    a = (ring 6, 5, 4, 3, 2, 1)
    live_loop :geschud do
      a = a.shuffle
      sleep 0.5
    end
    live_loop :gesorteerd do
      a = a.sort
      sleep 0.5
      puts "gesorteerd: ", a
    end

Laten we kijken hoe dit eruit ziet wanneer we `get` en `set` gebruiken:

    ## Een voorbeeld van deterministisch gedrag
    ## (ondanks gelijktijdige toegang tot gedeelde toestand)
    ## door het gebruik van het tijd toestand systeem van Sonic Pi.
    ##
    ## Wanneer deze code wordt uitgevoerd is de lijst
    ## die wordt afgedrukt altijd gesorteerd!
    set :a, (ring 6, 5, 4, 3, 2, 1)
    live_loop :geschud do
      set :a, get[:a].shuffle
      sleep 0.5
    end
    live_loop :gesorteerd do
      set :a, get[:a].sort
      sleep 0.5
      puts "gesorteerd: ", get[:a]
    end

Merk op dat de code bijna identiek is aan de versie die de variabele gebruikt hiervoor. Echter wanneer je de code uitvoert gedraagt het zich zoals je zou verwachten met elk typisch stuk Sonic Pi code: het doet elke keer hetzelfde in dit geval dankzij het tijd toestand systeem.

Gebruik daarom wanneer je informatie deelt tussen live lussen en threads `get` en `set` in plaat van variabelen voor deterministisch en reproduceerbaar gedrag.