How to give out the semitone steps in a scale with the help of the Ruby function each_cons

I wanted to give out the semitone steps in a scale: The result for (scale :C1, :blues_minor, num_octaves: 1) should be [3, 2, 1, 1, 3, 2]. With the help of Perplexity I stumbled over the very handy Ruby function each_cons, with which you can take a part of an array. If you combine this function with the map function the solution is a one-liner:

print "blues minor halftone steps: "
+ (scale :C1,  :blues_minor, num_octaves: 1).to_a.each_cons(2).map { |a, b| b - a }.to_s

1 Like

Also, if you’re comfortable enough with using the inner Sonic Pi source code in your composition,(with the understanding that there’s no guarantees internal functions remain the same into the future), you can access the scale intervals directly:

puts SonicPi::Scale::SCALE[:blues_minor]
=> [3, 2, 1, 1, 3, 2]

Scale names can be found in the ‘Lang’ section of the help window of course, or in the source code on GitHub at sonic-pi/app/server/ruby/lib/sonicpi/scale.rb at c14f85823db44040b78456ab5f8f5084953ef9e1 · sonic-pi-net/sonic-pi · GitHub.

1 Like

Thanks, that is really cute! But is there any documentation for this syntax with double colons? In the official help file I could not find anything.
This also works with chords, just tried it out

puts SonicPi::Chord::CHORD[:minor]

No documentation in Sonic Pi itself - the difference is that those functions in “SonicPi:: …” come from deep within Sonic Pi’s own source code, rather than the functions provided to users directly.
The ‘::’ is Ruby’s way of writing ‘namespaces’ - which are a way to organise modules of code into groups. You’d want to search for information about Ruby namespaces if you want to find out more.

Thanks, I found docs about ruby namespaces, for example here:
https://www.geeksforgeeks.org/ruby/namespaces-in-ruby/
I just realized that I can use .notes instead of .to_a in my first code example:

puts (scale :B4, :blues_minor).notes.each_cons(2).map { |a, b| b - a }

Thanks for that tip! I was unaware of each_cons, but it’s super handy. Nicely applied to scales, too!