1

I have some sonic pi code, and it is supposed to do a melody 8 times and play softer each time. However, it is not paying attention to the variable. Am I doing it wrong?

8.times do
  i = 1
  play 50, amp: 0.1 * i
  sleep 0.25
  play 55, amp: 0.2 * i
  sleep 0.25
  play 57, amp: 0.4 * i
  sleep 0.25
  play 62, amp: i
  i = i - 0.125
end

1 Answers1

3

Problems

You have at least three problems with your code:

  1. Your i variable is block-local, so it isn't propagating outside of your block. This may not be a significant problem, but it makes it harder to debug your code.
  2. You are explicitly resetting the value of i at the top of each loop with i = 1.
  3. The block doesn't memoize the value of i between calls to the block, so putting i ||= 1.0 at the top of the block doesn't really work either because i is always nil at the start of each loop.

Consider this minimal example of your existing code:

8.times { i = 1; i -= 0.125 }
i # NameError (undefined local variable or method `i' for main:Object)

Even if you introspect i within the block, you'll see that it never decrements with the current logic.

Solutions

The easiest way to fix your issues is to set the initial value of i outside your block. For example:

i = 1.0

8.times do
  i -= 0.125
  p i
end

i
#=> 0.0

With the Kernel#p statement, you can see the numbers counting down:

0.875
0.75
0.625
0.5
0.375
0.25
0.125
0.0

You can also see that you variable is now accessible outside of the block, and no longer returns a NameError when you access it after the block exits.

i
#=> 0.0
Todd A. Jacobs
  • 81,402
  • 15
  • 141
  • 199