Commented code still playing during 'Run'

I was trying to get my mind around some Sonic Pi coding and, as I do when I’m learning other programming languages, I tried running some code, commenting bits out, re-running the code, etc. to find out which bits were responsible for which parts of the song. But it looks like commenting out code doesn’t prevent it from being played. As my reproduction steps, I put in the following code:

##| define :foo do
##|   sleep 0.25
##|   play :c, sustain: 0.5
##|   sleep 0.25
##|   play :c, sustain: 0.5
##|   sleep 0.25
##|   play :c, sustain: 0.5
##|   sleep 0.25
##|   play :c, sustain: 0.5
##| end

foo
in_thread do
  foo
end

When I tried to run it, I got an error that foo was not defined (which is expected). When I uncomment the define :foo block (code below), the program runs and makes appropriate tones (which is also expected).

define :foo do
  sleep 0.25
  play :c, sustain: 0.5
  sleep 0.25
  play :c, sustain: 0.5
  sleep 0.25
  play :c, sustain: 0.5
  sleep 0.25
  play :c, sustain: 0.5
end

foo
in_thread do
  foo
end

But, when I comment out that code block again (so that it is identical to the first quoted code above), and click Run, the block plays identically to when that block was uncommented.

This seems very unintuitive. Is this behavior expected?

1 Like

the function definition remains in memory during a session. not sure if you can reset that without restarting the app. you could also manually run code like foo = nil or something in a different buffer.

1 Like

It might be easier to use the comment and uncomment commands I think?
Much simpler, as you dont have to comment out every line,

Eli…

@notb, I too thought that might be the issue. Figured I’d see if I was the only one who’d run into it and/or if it was “working as intended” vs “oh, well that’s unexpected”.

@Eli, in the code I was looking it, the blocks were calling other blocks sort of like this:

define :foo do
  sleep 0.25
  play :c
  ...
end

define bar do
  sleep 0.75
  play :a
  foo
  sleep 0.75
  play :a
  foo
  sleep 0.75
  play :a
  foo
  ...
end

I was trying to find out the interactions between the multiple blocks, but found that even when I had commented out all of the blocks, the code still ran unchanged. Commenting out the initial invocation of the blocks does prevent it from being played, but doesn’t help with the overall goal of trying to find out which output came from which block.

The easiest way to temporarily disable a live loop without commenting the loop then using stop and run in succession is merely to insert stop as the first line of the loop. YOu can then use run to rerun the loop and stop it. If you comment out the stop then rerun the loop will start again.

1 Like

@robin.newman , thanks for the reply, but I think I might not have explained things clearly originally. I was trying to point out is that it is not possible to disable a loop by commenting the loop, then using stop and run in succession. If there is something calling the loop name, the loop will continue to play with whatever it had in it prior to being commented (likely because, as @notb surmised the loop definition is still in the memory of the Spider Server).

I figured adding a stop or return or some other “escape early” language construct to the loop would do the disabling, but I wanted to find out if the way this works is expected/intended, or if it’s an unintended issue with the implementation.

(typing on a smart phone, so apologies in advance…)

This works as expected. I agree that it seems a bit unintuitive, but commenting out a function definition does not undefine it, so adding return is what you should do here.

@robin.newman is right: a stop is more useful inside of a live_loop or an in_thread block as that will stop the whole thread, but it’s probably not what you’re expecting either (which is to skip over the function).

@notb is also right. Let me try explaining this another way.

When you ”run" a sonic pi buffer, what you’re doing is causing the code in that buffer to be processed and the things (functions, variables, live-loops which are threaded functions) to be redefined. They remain defined until you quit Sonic Pi. In fact, you could define foo in one buffer, and then call it from the code in another, since it’s all the same Sonic Pi space.

So yes: put a return at the start of foo and then “run” to redefine foo, or as @notb said, def foo nil and then “run”, to undefine it (should give an error it you call it after that).

1 Like