10.1 Set en get

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

1. de informatie die we willen opslaan,
2. 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}##run: draai
 └─ 125.72265625
{run: 0, time: 0.5}##run: draai
 └─ 125.72265625
{run: 0, time: 1.0}##run: draai
 └─ 76.26220703125
{run: 0, time: 1.5}##run: draai
 └─ 76.26220703125
{run: 0, time: 2.0}##run: draai
 └─ 114.93408203125
{run: 0, time: 2.5}##run: draai
 └─ 114.93408203125
{run: 0, time: 3.0}##run: draai
 └─ 75.6048583984375
{run: 0, time: 3.5}##run: draai
 └─ 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.
