# Time state get and set issue

**URL:** <https://in-thread.sonic-pi.net/t/time-state-get-and-set-issue/9796>\
**Category:** Support, Help & Resources\
**Created:** [July 22, 2025, 1:37am UTC](https://in-thread.sonic-pi.net/t/time-state-get-and-set-issue/9796 "2025-07-22T01:37:16Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![nordicwing](https://avatars.discourse-cdn.com/v4/letter/n/ea666f/32.png) [@nordicwing](https://in-thread.sonic-pi.net/u/nordicwing)\
**Post date:** [July 22, 2025, 1:37am UTC](https://in-thread.sonic-pi.net/t/time-state-get-and-set-issue/9796/1 "2025-07-22T01:37:16Z")

</div>

I found the sample code in the tutorial highly dependent on the order of live\_loop defined, if I switch the order of those two live\_loops (in the tutorial it defines the shuffle ahead of sorted), as such below, the result would be again in a chaos like without using time state.

```ruby
## 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 :sorted do
  set :a, get[:a].sort
  sleep 0.5
  puts "sorted: ", get[:a]
end

live_loop :shuffled do
  set :a, get[:a].shuffle
  sleep 0.5
end

```

the output is:

```ruby
=> Starting run 11

=> Redefining fn :live_loop_sorted

=> Redefining fn :live_loop_shuffled

{run: 11, time: 0.5, thread: :live_loop_sorted}
 └─ "sorted: " (ring 4, 6, 2, 3, 1, 5)
 
{run: 11, time: 1.0, thread: :live_loop_sorted}
 └─ "sorted: " (ring 6, 2, 3, 5, 1, 4)
 
{run: 11, time: 1.5, thread: :live_loop_sorted}
 └─ "sorted: " (ring 1, 3, 5, 6, 2, 4)
 
{run: 11, time: 2.0002, thread: :live_loop_sorted}
 └─ "sorted: " (ring 3, 2, 4, 1, 6, 5)
 
=> Stopping all runs...

=> Stopping run 11

{run: 11, time: 2.5002, thread: :live_loop_sorted}
 └─ "sorted: " (ring 1, 4, 6, 5, 2, 3)
 
{run: 11, time: 3.0002, thread: :live_loop_sorted}
 └─ "sorted: " (ring 6, 5, 4, 1, 2, 3)
 
=> Completed run 11

=> All runs completed

=> Pausing SuperCollider Audio Server

```

I believe the key reason is rather happening in the sleep 0.5, when shuffle may take part in no matter whether you use getter and setter or not.  
But the problem is if I simply change the order of the loops defined, like this

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

```

then the output is changed as well, that means the result can’t be controlled

```ruby
=> Starting run 17

=> Defining fn :live_loop_shuffled

=> Redefining fn :live_loop_sorted

{run: 17, time: 0.5001, thread: :live_loop_sorted}
 └─ "sorted: " (ring 1, 2, 3, 4, 5, 6)
 
{run: 17, time: 1.0, thread: :live_loop_sorted}
 └─ "sorted: " (ring 1, 2, 3, 4, 5, 6)
 
{run: 17, time: 1.5, thread: :live_loop_sorted}
 └─ "sorted: " (ring 1, 2, 3, 4, 5, 6)
 
=> Stopping all runs...

=> Stopping run 17

{run: 17, time: 2.0, thread: :live_loop_sorted}
 └─ "sorted: " (ring 1, 2, 3, 4, 5, 6)
 
{run: 17, time: 2.5, thread: :live_loop_sorted}
 └─ "sorted: " (ring 1, 2, 3, 4, 5, 6)
 
=> Completed run 17

=> All runs completed

=> Pausing SuperCollider Audio Server

```

---

<div class="post-metadata">

**Author:** ![boda](https://avatars.discourse-cdn.com/v4/letter/b/ecae2f/32.png) [@boda](https://in-thread.sonic-pi.net/u/boda)\
**Post date:** [July 22, 2025, 2:47am UTC](https://in-thread.sonic-pi.net/t/time-state-get-and-set-issue/9796/2 "2025-07-22T02:47:43Z")

</div>

> [@nordicwing](#):
>
> ```ruby
> set :a, (ring 6, 5, 4, 3, 2, 1)
> 
> live_loop :sorted do
> set :a, get[:a].sort
> sleep 0.5
> puts "sorted: ", get[:a]
> end
> 
> live_loop :shuffled do
> set :a, get[:a].shuffle
> sleep 0.5
> end
> 
> ```

Hello! Thanks for asking.

I’m not entirely sure about your question, but the behavior you’re seeing is actually completely deterministic. Try the following:

```ruby
set :a, (ring 6, 5, 4, 3, 2, 1)

live_loop :sorted do
  set :a, get[:a].sort
  puts "sorted: ", get[:a]
  sleep 0.5
  puts "sorted: ", get[:a]
end

live_loop :inverse do
  set :a, get[:a].sort.reverse
  sleep 0.5
end

```

I’m assuming you’re seeing that misbehavior because `puts` is getting the state once it’s modified, but otherwise everything seems as expected.

let me know if I made myself clear 🤔

---

<div class="post-metadata">

**Author:** ![nordicwing](https://avatars.discourse-cdn.com/v4/letter/n/ea666f/32.png) [@nordicwing](https://in-thread.sonic-pi.net/u/nordicwing)\
**Post date:** [July 22, 2025, 4:52am UTC](https://in-thread.sonic-pi.net/t/time-state-get-and-set-issue/9796/3 "2025-07-22T04:52:56Z")

</div>

Hi, thank you for the reply. I have tried with your code and here is the output, it is indeterministic:

```ruby
=> Starting run 15

=> Defining fn :live_loop_sorted

=> Defining fn :live_loop_inverse

{run: 15, time: 0.0, thread: :live_loop_sorted}
 └─ "sorted: " (ring 1, 2, 3, 4, 5, 6)
 
{run: 15, time: 0.5, thread: :live_loop_sorted}
 ├─ "sorted: " (ring 6, 5, 4, 3, 2, 1)
 └─ "sorted: " (ring 1, 2, 3, 4, 5, 6)
 
{run: 15, time: 1.0, thread: :live_loop_sorted}
 ├─ "sorted: " (ring 6, 5, 4, 3, 2, 1)
 └─ "sorted: " (ring 1, 2, 3, 4, 5, 6)
 
{run: 15, time: 1.5, thread: :live_loop_sorted}
 ├─ "sorted: " (ring 6, 5, 4, 3, 2, 1)
 └─ "sorted: " (ring 1, 2, 3, 4, 5, 6)
 
{run: 15, time: 2.0001, thread: :live_loop_sorted}
 ├─ "sorted: " (ring 6, 5, 4, 3, 2, 1)
 └─ "sorted: " (ring 1, 2, 3, 4, 5, 6)
 
{run: 15, time: 2.5001, thread: :live_loop_sorted}
 ├─ "sorted: " (ring 6, 5, 4, 3, 2, 1)
 └─ "sorted: " (ring 1, 2, 3, 4, 5, 6)
 
{run: 15, time: 3.0001, thread: :live_loop_sorted}
 ├─ "sorted: " (ring 6, 5, 4, 3, 2, 1)
 └─ "sorted: " (ring 1, 2, 3, 4, 5, 6)
 
{run: 15, time: 3.5001, thread: :live_loop_sorted}
 ├─ "sorted: " (ring 6, 5, 4, 3, 2, 1)
 └─ "sorted: " (ring 1, 2, 3, 4, 5, 6)
 
{run: 15, time: 4.0001, thread: :live_loop_sorted}
 ├─ "sorted: " (ring 6, 5, 4, 3, 2, 1)
 └─ "sorted: " (ring 1, 2, 3, 4, 5, 6)
 
{run: 15, time: 4.5001, thread: :live_loop_sorted}
 ├─ "sorted: " (ring 6, 5, 4, 3, 2, 1)
 └─ "sorted: " (ring 1, 2, 3, 4, 5, 6)
 
{run: 15, time: 5.0001, thread: :live_loop_sorted}
 ├─ "sorted: " (ring 6, 5, 4, 3, 2, 1)
 └─ "sorted: " (ring 1, 2, 3, 4, 5, 6)
 
=> Stopping all runs...

=> Stopping run 15

{run: 15, time: 5.5001, thread: :live_loop_sorted}
 ├─ "sorted: " (ring 6, 5, 4, 3, 2, 1)
 └─ "sorted: " (ring 1, 2, 3, 4, 5, 6)
 
=> Completed run 15

=> All runs completed

=> Pausing SuperCollider Audio Server

```

please understand why I’m saying so, because if I just define the two loops in another order, I will have different output,

```ruby
set :a, (ring 6, 5, 4, 3, 2, 1)

live_loop :inverse do
  set :a, get[:a].sort.reverse
  sleep 0.5
end

live_loop :sorted do
  set :a, get[:a].sort
  puts "sorted: ", get[:a]
  sleep 0.5
  puts "sorted: ", get[:a]
end

```

```ruby
=> Starting run 16

=> Redefining fn :live_loop_inverse

=> Redefining fn :live_loop_sorted

{run: 16, time: 0.0, thread: :live_loop_sorted}
 └─ "sorted: " (ring 1, 2, 3, 4, 5, 6)
 
{run: 16, time: 0.4999, thread: :live_loop_sorted}
 ├─ "sorted: " (ring 1, 2, 3, 4, 5, 6)
 └─ "sorted: " (ring 1, 2, 3, 4, 5, 6)
 
{run: 16, time: 1.0002, thread: :live_loop_sorted}
 ├─ "sorted: " (ring 1, 2, 3, 4, 5, 6)
 └─ "sorted: " (ring 1, 2, 3, 4, 5, 6)
 
{run: 16, time: 1.5002, thread: :live_loop_sorted}
 ├─ "sorted: " (ring 1, 2, 3, 4, 5, 6)
 └─ "sorted: " (ring 1, 2, 3, 4, 5, 6)
 
{run: 16, time: 2.0002, thread: :live_loop_sorted}
 ├─ "sorted: " (ring 1, 2, 3, 4, 5, 6)
 └─ "sorted: " (ring 1, 2, 3, 4, 5, 6)
 
=> Stopping all runs...

=> Stopping run 16

{run: 16, time: 2.5002, thread: :live_loop_sorted}
 ├─ "sorted: " (ring 1, 2, 3, 4, 5, 6)
 └─ "sorted: " (ring 1, 2, 3, 4, 5, 6)
 
=> Completed run 16

=> All runs completed

=> Pausing SuperCollider Audio Server

```

---

<div class="post-metadata">

**Author:** ![boda](https://avatars.discourse-cdn.com/v4/letter/b/ecae2f/32.png) [@boda](https://in-thread.sonic-pi.net/u/boda)\
**Post date:** [July 23, 2025, 2:02am UTC](https://in-thread.sonic-pi.net/t/time-state-get-and-set-issue/9796/4 "2025-07-23T02:02:56Z")

</div>

🤔, lets forget about the puts. if I use it with sound I hear same sound pattern no matter where I put the order of the loops

```ruby
use_random_seed 1

set :a, (ring 20, 40, 60, 80, 90)

live_loop :sorted do
  use_synth :dsaw
  set :a, get[:a].sort
  play get[:a].tick
  sleep 2
end

live_loop :inverse do
  set :a, get[:a].sort.reverse
  play get[:a].tick
  sleep 2
end

```

---

<div class="post-metadata">

**Author:** ![nordicwing](https://avatars.discourse-cdn.com/v4/letter/n/ea666f/32.png) [@nordicwing](https://in-thread.sonic-pi.net/u/nordicwing)\
**Post date:** [July 23, 2025, 7:46am UTC](https://in-thread.sonic-pi.net/t/time-state-get-and-set-issue/9796/5 "2025-07-23T07:46:23Z")

</div>

> [@boda](#):
>
> ```ruby
> use_random_seed 1
> 
> set :a, (ring 20, 40, 60, 80, 90)
> 
> live_loop :sorted do
> use_synth :dsaw
> set :a, get[:a].sort
> play get[:a].tick
> sleep 2
> end
> 
> live_loop :inverse do
> set :a, get[:a].sort.reverse
> play get[:a].tick
> sleep 2
> end
> 
> ```

well, actually no. You changed the sleep position. Try this code and change the order of definition of loops, you will hear different things.

```ruby
use_random_seed 1

set :a, (ring 20, 40, 60, 80, 90)

live_loop :sorted do
  use_synth :dsaw
  set :a, get[:a].sort
  sleep 2
  play get[:a].tick
end

live_loop :inverse do
  set :a, get[:a].sort.reverse
  play get[:a].tick
  sleep 2
end

```

---

<div class="post-metadata">

**Author:** ![boda](https://avatars.discourse-cdn.com/v4/letter/b/ecae2f/32.png) [@boda](https://in-thread.sonic-pi.net/u/boda)\
**Post date:** [July 25, 2025, 2:09am UTC](https://in-thread.sonic-pi.net/t/time-state-get-and-set-issue/9796/6 "2025-07-25T02:09:27Z")

</div>

> [@nordicwing](#):
>
> ```ruby
> use_random_seed 1
> 
> set :a, (ring 20, 40, 60, 80, 90)
> 
> live_loop :sorted do
> use_synth :dsaw
> set :a, get[:a].sort
> sleep 2
> play get[:a].tick
> end
> 
> live_loop :inverse do
> set :a, get[:a].sort.reverse
> play get[:a].tick
> sleep 2
> end
> 
> ```

yes it sounds different from the one I send and makes sense, cause Is `sorted` `sleep 2` acts first, but If I grab the code you send, and I press play I am hearing the same pattern always.

maybe I am missing something 🤔

---

<div class="post-metadata">

**Author:** ![ethancrawford](https://avatars.discourse-cdn.com/v4/letter/e/a88e4f/32.png) [@ethancrawford](https://in-thread.sonic-pi.net/u/ethancrawford)\
**Post date:** [July 25, 2025, 4:36am UTC](https://in-thread.sonic-pi.net/t/time-state-get-and-set-issue/9796/7 "2025-07-25T04:36:51Z")

</div>

> [@boda](#):
>
> I am hearing the same pattern always

The individual patterns played by each loop do not change _between runs_, so in that respect, you’ll hear the same patterns being played over time. However, the order in which the two loops are defined _determines the patterns that are played_. If I understand correctly I think what nordicwing is getting at is that they believe it should not do so…

---

<div class="post-metadata">

**Author:** ![nordicwing](https://avatars.discourse-cdn.com/v4/letter/n/ea666f/32.png) [@nordicwing](https://in-thread.sonic-pi.net/u/nordicwing)\
**Post date:** [July 25, 2025, 5:51am UTC](https://in-thread.sonic-pi.net/t/time-state-get-and-set-issue/9796/8 "2025-07-25T05:51:14Z")

</div>

> [@boda](#):
>
> maybe I am missing something 🤔

No, you are right, that’s also what I’m thinking, during the sleep things are changed. But still, just by changing the position of definition we get indeterministic result. And also, the way of the code I sent you is from the tutorial, it’s like a official guide of practice, but this way of coding can’t guarantee the result.

---

<div class="post-metadata">

**Author:** ![nordicwing](https://avatars.discourse-cdn.com/v4/letter/n/ea666f/32.png) [@nordicwing](https://in-thread.sonic-pi.net/u/nordicwing)\
**Post date:** [July 25, 2025, 5:56am UTC](https://in-thread.sonic-pi.net/t/time-state-get-and-set-issue/9796/9 "2025-07-25T05:56:19Z")

</div>

Yes you are right, that’s what I’m concerned. Also the code is actually from the tutorial,

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

```

If you swap the order of the two definitions, it outputs the different results – just as the indeterministic result without using time state shown by the example previously.

---

<div class="post-metadata">

**Author:** ![samaaron](https://dub1.discourse-cdn.com/flex017/user_avatar/in-thread.sonic-pi.net/samaaron/32/7_2.png) [@samaaron](https://in-thread.sonic-pi.net/u/samaaron)\
**Post date:** [July 26, 2025, 8:00am UTC](https://in-thread.sonic-pi.net/t/time-state-get-and-set-issue/9796/10 "2025-07-26T08:00:23Z")

</div>

The guiding principle of Sonic Pi’s determinism is that the same code should produce the same results.

The important thing to note is that A, B, C is not the same as B, A, C - and this counts for the ordering of Sonic Pi’s Live Loops too. Order matters and is key to solving race conditions deterministically.

If you say “the two Live Loops are concurrent, they surly can be switched in place and have the same result” then you need to have a good answer as to how race conditions between the two threads are solved deterministically. This is especially true in very esoteric cases like your example where you’re explicitly trying to get the two threads to modify the same state at the same time! It’s almost like you’re looking for the edge cases!

---

<div class="post-metadata">

**Author:** ![HarryLeBlanc](https://dub1.discourse-cdn.com/flex017/user_avatar/in-thread.sonic-pi.net/harryleblanc/32/2813_2.png) [@HarryLeBlanc](https://in-thread.sonic-pi.net/u/HarryLeBlanc)\
**Post date:** [July 27, 2025, 2:48pm UTC](https://in-thread.sonic-pi.net/t/time-state-get-and-set-issue/9796/11 "2025-07-27T14:48:21Z")

</div>

On a practical level, couldn’t you just make two local copies of the array inside each loop, and tick through those? That way the data each loop was traversing would be encapsulated in the loop and immune to weird side effects. This just seems like good programming hygiene.

```ruby
## 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
  shuffleloop = get[:a].shuffle
  sleep 0.5
end

live_loop :sorted do
  sortloop = get[:a].sort
  sleep 0.5
  puts "sorted: ", sortloop
end

```
