Paramétrer et obtenir

Sonic Pi a un magasin de mémoire global appelé État du Temps. Les deux choses principales que vous faites avec sont de set de l’information et de get de l’information. Explorons plus en détails…

Paramétrer

Pour stocker de l’information dans l’État du Temps, nous avons besoin de deux choses :

  1. l’information que nous voulons stocker,
  2. un nom unique (clé) pour l’information.

Par exemple, nous voulons stocker le chiffre 3000 avec la clé :intensity. C’est possible en utilisant la fonction set :

set :intensity, 3000

Nous pouvons utiliser n’importe quel nom pour notre clé. Si de l’information a déjà été stockée avec cette clé, notre nouveau set va l’écraser :

set :intensity, 1000
set :intensity, 3000

Dans l’exemple ci-dessus, étant donné que nous stockons deux nombres avec la même clé, le dernier appel à set “gagne”, alors le nombre associé à :intensity sera 3000 étant donné que le premier appel à set est écrasé.

Obtenir

Pour obtenir de l’information de l’État du Temps, nous avons seulement besoin de la clé que nous avons utilisée pour la set, qui est dans notre cas :intensity. Nous avons alors seulement besoin d’appeler get[:intensity] que nous pouvons voir en affichant le résultat dans le journal :

print get[:intensity] #=> prints 3000

Notez que l’appel à get peut retourner de l’information qui a été set dans une exécution précédente. Une fois qu’une pièce d’information a été set, elle est disponible jusqu’à ce qu’elle soit écrasée (comme nous l’avons fait avec la valeur de :intensity passant de 1000 à 3000 ci-dessus) ou que Sonic Pi soit fermé.

Fils multiples

L’avantage principal du système d’État du Temps est qu’il peut être utilisé de façon sûre au travers des fils d’exécution ou des boucles en direct. Par exemple, vous pourriez avoir une boucle en direct qui affecte de l’information et une autre qui l’obtient :

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

La chose plaisante avec l’utilisation de get et set au travers des fils d’exécution de cette façon est que ça produira toujours le même résultat à chaque fois que vous l’exécuterez. Allez-y, essayez-le. Regardez si vous obtenez le journal suivant :

{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

Essayez de l’exécuter quelques fois - vous voyez, c’est toujours la même chose. C’est ce qu’on appelle un comportement déterministe et c’est très important quand nous voulons partager notre musique sous forme de code et que nous savons que la personne qui exécute le code entend exactement ce que nous voulions qu’elle entende (tout comme jouer un MP3 ou flux d’internet sonne de la même façon pour tout ceux qui écoutent).

Un système d’état simple et déterministe

À la Section 5.6, nous avons discuté de pourquoi l’utilisation des variables à travers les fils peut entraîner des comportements hasardeux. Ceci nous empêche de pouvoir, de façon sûre, reproduire du code comme ceci :

## Un exemple de comportement non-déterministe
## (du à la concurrence causée pas de multiple
## boucles en direct qui manipule la même variable
## au même moment).
##  
## Si vous exécutez ce code, vous remarquerez
## que la liste qui est imprimée
## n'est pas toujours triée!
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

Regardons à quoi cela peut ressembler en utilisant get and set :

## Un exemple de comportement déterministe
## (malgré l'accès avec concurrence de l'état partagé)
## en utilisant le nouveau système d'État du Temps de Sonic Pi.
##
## Quand ce code est exécuté, la liste qui est
## imprimée est toujours triée!
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

Remarquez comment le code est pratiquement identique à la version qui utilisait la variable auparavant. Cependant, quand vous exécutez votre code, il agit de la façon que vous vous attendez comme avec n’importe lequel code de Sonic Pi typique - il fait la même chose chaque fois dans ce cas grâce au système d’État du Temps.

Donc, lorsque vous partagez de l’information au travers de boucles en direct et de fils d’exécution, utilisez get et set au lieu de variables pour un comportement déterministe et reproductible.