# Shifting Rings from Spread

**URL:** <https://in-thread.sonic-pi.net/t/shifting-rings-from-spread/2418>\
**Category:** Support, Help & Resources\
**Created:** [May 24, 2019, 7:48am UTC](https://in-thread.sonic-pi.net/t/shifting-rings-from-spread/2418 "2019-05-24T07:48:39Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![chris.krakou](https://avatars.discourse-cdn.com/v4/letter/c/e5b9ba/32.png) [@chris.krakou](https://in-thread.sonic-pi.net/u/chris.krakou)\
**Post date:** [May 24, 2019, 7:48am UTC](https://in-thread.sonic-pi.net/t/shifting-rings-from-spread/2418/1 "2019-05-24T07:48:40Z")

</div>

Hello Folks

I’ve been using spread a lot to generate euclidean rhythms, and they work really well. One thing I can’t seem to figure out is how to shift them. For instance, `spread(2,16)` gives me a hit on 1 and 8, which sounds off when I try to add snares from one measure to the next. Is there an easy way to “pre-tick” it 4 times, so i get a hit on 5 and 13 instead?

aka. from  
`(ring true, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false)`  
to  
`(ring false, false, false, false, true, false, false, false, false, false, false, false, true, false, false, false)`

---

<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:** [May 24, 2019, 7:58am UTC](https://in-thread.sonic-pi.net/t/shifting-rings-from-spread/2418/2 "2019-05-24T07:58:26Z")

</div>

Hi @chris.krakou,

lovely question! You can skip or “rotate” a spread an arbitrary number of times using the `.rotate` modifier:

```ruby
(spread 2,16).rotate(4)  

```

You can use positive or negative values for the rotate amount.

I hope that this helps 🙂

---

<div class="post-metadata">

**Author:** ![Martin](https://dub1.discourse-cdn.com/flex017/user_avatar/in-thread.sonic-pi.net/martin/32/157_2.png) [@Martin](https://in-thread.sonic-pi.net/u/Martin)\
**Post date:** [May 24, 2019, 10:43am UTC](https://in-thread.sonic-pi.net/t/shifting-rings-from-spread/2418/3 "2019-05-24T10:43:42Z")

</div>

Hi @samaaron,

according to my tests

```ruby
v = 1
spread(2, 8, rotate: v)

```

will always return:

```ruby
(ring true, false, false, false, true, false, false, false)

```

no matter what value `v` has. At least in my SP 3.1.0

which is consitant with the documentation:

“… rotate _to the next strong_ beat allowing for easy permutations of the original rhythmic grouping …”.

I would be glad if I am wrong because I was already looking for an easy way to shift beats irrespective of them being week or strong.

---

<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:** [May 24, 2019, 11:12am UTC](https://in-thread.sonic-pi.net/t/shifting-rings-from-spread/2418/4 "2019-05-24T11:12:22Z")

</div>

Hi @Martin,

yes, that would make sense. The _option_ `rotate:` is different from the modifier `.rotate`. In other words, the option `rotate:` is specific to the `spread` function whereas the modifier `.rotate` works on any ring.

Note the difference:

```ruby
(spread 2, 8, rotate: 4)
(spread 2, 8).rotate(4)

```

Hope that this helps 🙂

---

<div class="post-metadata">

**Author:** ![Martin](https://dub1.discourse-cdn.com/flex017/user_avatar/in-thread.sonic-pi.net/martin/32/157_2.png) [@Martin](https://in-thread.sonic-pi.net/u/Martin)\
**Post date:** [May 24, 2019, 11:17am UTC](https://in-thread.sonic-pi.net/t/shifting-rings-from-spread/2418/5 "2019-05-24T11:17:03Z")

</div>

Ahh!! Great! Thanks for clearing up my misunderstanding and misreading.

---

<div class="post-metadata">

**Author:** ![chris.krakou](https://avatars.discourse-cdn.com/v4/letter/c/e5b9ba/32.png) [@chris.krakou](https://in-thread.sonic-pi.net/u/chris.krakou)\
**Post date:** [May 24, 2019, 8:02pm UTC](https://in-thread.sonic-pi.net/t/shifting-rings-from-spread/2418/6 "2019-05-24T20:02:25Z")

</div>

That’s exactly what i needed. Thanks @samaaron!

The .rotate function doesn’t appear anywhere in the built-in documentation. Finding the functions built into rings (beyond the tutorial) is generally a bit difficult, it would be nice if all the functions were listed in the ring entry.

I could write a bit about it if you want. Just give a hint as to where I should put it.

---

<div class="post-metadata">

**Author:** ![Eli](https://dub1.discourse-cdn.com/flex017/user_avatar/in-thread.sonic-pi.net/eli/32/116_2.png) [@Eli](https://in-thread.sonic-pi.net/u/Eli)\
**Post date:** [May 24, 2019, 9:30pm UTC](https://in-thread.sonic-pi.net/t/shifting-rings-from-spread/2418/7 "2019-05-24T21:30:28Z")

</div>

Hi Chris,

I think .rotate is really a Ruby construct, and as such not documented in the SP help…

There are others, .mirror, .reverse, which come to mind, which were mentioned in another  
much older post, somewhere.

Sam usually says they aren’t formally supported, even though they might work, and may not  
work in future versions… which would be a shame, as they are damn useful.

Eli…

---

<div class="post-metadata">

**Author:** ![Martin](https://dub1.discourse-cdn.com/flex017/user_avatar/in-thread.sonic-pi.net/martin/32/157_2.png) [@Martin](https://in-thread.sonic-pi.net/u/Martin)\
**Post date:** [May 25, 2019, 7:23am UTC](https://in-thread.sonic-pi.net/t/shifting-rings-from-spread/2418/8 "2019-05-25T07:23:03Z")

</div>

> [@Eli](#):
>
> in another  
> much older post, somewhere

… and here: [https://github.com/samaaron/sonic-pi/blob/master/etc/doc/tutorial/08.5-Ring-Chains.md](https://github.com/samaaron/sonic-pi/blob/master/etc/doc/tutorial/08.5-Ring-Chains.md)

---

<div class="post-metadata">

**Author:** ![Eli](https://dub1.discourse-cdn.com/flex017/user_avatar/in-thread.sonic-pi.net/eli/32/116_2.png) [@Eli](https://in-thread.sonic-pi.net/u/Eli)\
**Post date:** [May 25, 2019, 8:18am UTC](https://in-thread.sonic-pi.net/t/shifting-rings-from-spread/2418/9 "2019-05-25T08:18:42Z")

</div>

What he said. 🙂

---

<div class="post-metadata">

**Author:** ![chris.krakou](https://avatars.discourse-cdn.com/v4/letter/c/e5b9ba/32.png) [@chris.krakou](https://in-thread.sonic-pi.net/u/chris.krakou)\
**Post date:** [May 25, 2019, 11:51am UTC](https://in-thread.sonic-pi.net/t/shifting-rings-from-spread/2418/10 "2019-05-25T11:51:20Z")

</div>

I sat down and went through the [ruby array operators](https://www.sitepoint.com/guide-ruby-collections-part-arrays/) to check which ones work and which ones don’t as of today (version 3.1.0), in case someone else comes across this thread.

```
###########
# WORKS
###########

# Transformations
puts (scale :a1, :minor) << 88
puts (scale :a1, :minor).unshift(33)
puts (scale :a1, :minor).push(33)
puts (scale :a1, :minor).pop
puts (scale :a1, :minor).shift
puts (scale :a1, :minor).delete_at(1)
puts (scale :a1, :minor).reverse

# Combining
puts (scale :c1,:major) + (scale :c2,:major)
puts (scale :c1,:major) + (scale :d1,:major).uniq
puts (scale :c1,:major) - (scale :d1,:major)

# Removing Duplicates
puts (scale :c1,:major).concat((scale :d1, :major))

# Moving
puts (scale :c1,:major).reverse
puts (scale :c1,:major).rotate
puts (scale :c1,:major).rotate(-2)

# Querying
puts (scale :c1,:major).include? 29
puts (scale :c1,:major).count 29
puts (scale :c1,:major).size

# Iterations
(scale :c1, :major).each {|i| puts i}
(scale :c1, :major).reverse_each {|i| puts i}
(scale :c1, :major).each_with_index do |note,index|
  puts "#{note} at #{index} "
end

###########
# DOESN'T WORK
###########

# boolean operators
puts testring & (scale :d1,:minor)
puts testring | (scale :d1,:minor)

# Joining
puts (ring "hello","world").join
```

---

<div class="post-metadata">

**Author:** ![Hussein](https://dub1.discourse-cdn.com/flex017/user_avatar/in-thread.sonic-pi.net/hussein/32/1972_2.png) [@Hussein](https://in-thread.sonic-pi.net/u/Hussein)\
**Post date:** [June 1, 2021, 11:09am UTC](https://in-thread.sonic-pi.net/t/shifting-rings-from-spread/2418/11 "2021-06-01T11:09:40Z")

</div>

Hi everyone

going to revive this thread, as I am also interested in Euclid generated patterns.  
I have the [VPME.DE](http://VPME.DE) Circles and it has a mode where it also outputs the inverse. I had wondered how to do this with Sonic Pi and realised that it was a question of evaluating whether a ring item was true or false. I’m sure there are more refined ways to achieve this but, generally pleased with the result, especially the variable rotate. The inverse (false) would be good to deploy for alternating between open/closed hats.

```ruby
live_loop :euclidPatt do
  ticky = tick
  
  if one_in(6)
    rot = rrand_i(0,2)
  else
    rot = 0
  end
  
  t = (spread 3,8, rotate:rot)
  #Positive
  sample :perc_snap, release: 0.2, pan: -1, amp: 0.3 if (t[ticky] == true)
  #Inverse of the Eucild pattern
  sample :elec_flip, rate: 2, release: 0.2, pan: 1, amp: 0.4 if (t[ticky] == false)
  sleep 0.25
end

```

Cheers  
Hussein

---

<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:** [June 1, 2021, 7:22pm UTC](https://in-thread.sonic-pi.net/t/shifting-rings-from-spread/2418/12 "2021-06-01T19:22:05Z")

</div>

Hi @Hussein,

I might rewrite your code as the following:

```ruby
live_loop :euclidPatt do  
  tick
  if one_in(6)
    rot = rrand_i(0,2)
  else
    rot = 0
  end
  
  t = (spread 3,8, rotate:rot)
  #Positive
  sample :perc_snap, release: 0.2, pan: -1, amp: 0.3, on: t.look
  #Inverse of the Eucild pattern
  sample :elec_flip, rate: 2, release: 0.2, pan: 1, amp: 0.4, on: !t.look
  sleep 0.25
end

```

Note, that I just call `tick` (there’s no need to assign the result as you can use `.look` to “look it up” later). I then use the `on:` opt instead of `if` as this lets you put the option anywhere in the options and not just at the end. It also supports counting `1` as true and `0` as false which can be useful in other situations. Finally I used the `!` modifier which returns the logical inversion of the value (`!true == false`).

I hope that this helps 🙂

---

<div class="post-metadata">

**Author:** ![Hussein](https://dub1.discourse-cdn.com/flex017/user_avatar/in-thread.sonic-pi.net/hussein/32/1972_2.png) [@Hussein](https://in-thread.sonic-pi.net/u/Hussein)\
**Post date:** [June 1, 2021, 8:09pm UTC](https://in-thread.sonic-pi.net/t/shifting-rings-from-spread/2418/13 "2021-06-01T20:09:55Z")

</div>

Hi @samaaron cheers for the adaptation.

I sometimes run into issues using the !, i.e. not flipping when I expect it to.

In respect of `on:` is this preferred rather than using if? I’ve wondered about additional `opts` after the `if` statement, so this is good to know.

Much appreciated.

---

<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:** [June 1, 2021, 8:12pm UTC](https://in-thread.sonic-pi.net/t/shifting-rings-from-spread/2418/14 "2021-06-01T20:12:45Z")

</div>

> [@Hussein](#):
>
> I sometimes run into issues using the !, i.e. not flipping when I expect it to.

I’d love to see an example of this behaviour.

> In respect of `on:` is this preferred rather than using if? I’ve wondered about additional `opts` after the `if` statement, so this is good to know.

I certainly prefer it (and designed it) for the reasons I stated above 🙂

---

<div class="post-metadata">

**Author:** ![Hussein](https://dub1.discourse-cdn.com/flex017/user_avatar/in-thread.sonic-pi.net/hussein/32/1972_2.png) [@Hussein](https://in-thread.sonic-pi.net/u/Hussein)\
**Post date:** [June 1, 2021, 8:27pm UTC](https://in-thread.sonic-pi.net/t/shifting-rings-from-spread/2418/15 "2021-06-01T20:27:46Z")

</div>

yes, I’d love to make it happen consistently. I’m not saying it’s SPi, just getting odd results, that I need to better understand what might be causing them.

I was wondering about `on` because I picked up the `if(spread...` from the help docs. So if I read this right, `on` is good to use where the `ring` is in a variable result from running `spread`, rather than inline after `amp:` using an `if` statement. is that correct or gone down the wrong rabbit hole?

Cheers.

---

<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:** [June 1, 2021, 8:41pm UTC](https://in-thread.sonic-pi.net/t/shifting-rings-from-spread/2418/16 "2021-06-01T20:41:56Z")

</div>

> [@Hussein](#):
>
> So if I read this right, `on` is good to use where the `ring` is in a variable result from running `spread` , rather than inline after `amp:` using an `if` statement. is that correct or gone down the wrong rabbit hole?

Essentially I’d use `on:` instead of a trailing `if` in all cases - unless I know specifically that I need an `if`.

The main semantic difference (which is rarely significant) is that the a false value after a trailing `if` causes _none of the statement preceding the `if` to be executed_. It’s as if that line wasn’t part of the code. However, with the `on:` opt, the line _is_ executed, just that the synth or MIDI note isn’t triggered if the value is `false`, `nil` or `0` (note that `if` treats `0` as a truthy value).

---

<div class="post-metadata">

**Author:** ![Hussein](https://dub1.discourse-cdn.com/flex017/user_avatar/in-thread.sonic-pi.net/hussein/32/1972_2.png) [@Hussein](https://in-thread.sonic-pi.net/u/Hussein)\
**Post date:** [June 1, 2021, 8:45pm UTC](https://in-thread.sonic-pi.net/t/shifting-rings-from-spread/2418/17 "2021-06-01T20:45:23Z")

</div>

So unless an explicit need for an `if`, always use `on`.  
Thanks for that, I’ll move in this general direction.

---

<div class="post-metadata">

**Author:** ![enkerli](https://dub1.discourse-cdn.com/flex017/user_avatar/in-thread.sonic-pi.net/enkerli/32/54_2.png) [@enkerli](https://in-thread.sonic-pi.net/u/enkerli)\
**Post date:** [August 15, 2021, 10:04pm UTC](https://in-thread.sonic-pi.net/t/shifting-rings-from-spread/2418/18 "2021-08-15T22:04:12Z")

</div>

Also reviving this thread as I’m getting syntax errors from the code @chris.krakou (in version 3.3.1).

```ruby
# Not working
# Transformations
##| puts (scale :a1, :minor) << 88
##| puts (scale :a1, :minor).unshift(33)
##| puts (scale :a1, :minor).push(33)
##| puts (scale :a1, :minor).pop
##| puts (scale :a1, :minor).shift
##| puts (scale :a1, :minor).delete_at(1)

# Removing Duplicates
##| puts (scale :c1,:major).concat((scale :d1, :major))

# Querying
##| puts (scale :c1,:major).include? 29
##| puts (scale :c1,:major).count 29

# Iterations
##| (scale :c1, :major).reverse_each {|i| puts i}

```

No idea what’s changed since 3.1.0… and I’m “too lazy” to check now.

---

<div class="post-metadata">

**Author:** ![robin.newman](https://avatars.discourse-cdn.com/v4/letter/r/76d3ee/32.png) [@robin.newman](https://in-thread.sonic-pi.net/u/robin.newman)\
**Post date:** [August 16, 2021, 8:04am UTC](https://in-thread.sonic-pi.net/t/shifting-rings-from-spread/2418/19 "2021-08-16T08:04:28Z")

</div>

The change is that scales are now treated as rings. You need to convert to lists and remove extraneous bits at start. To be fair you are using Ruby constructs like \<\< .push .pop and these are not guaranteed to work.

The solution looks like this:

```ruby
# Not working
# Transformations
puts (scale :a1, :minor).to_a.flatten << 88

puts (scale :a1, :minor).to_a.flatten.unshift(33)
puts (scale :a1, :minor).to_a.flatten.push(33)
puts (scale :a1, :minor).to_a.flatten.pop
puts (scale :a1, :minor).to_a.flatten.shift
puts (scale :a1, :minor).to_a.flatten.delete_at(1)

# Removing Duplicates
puts (scale :c1,:major).to_a.flatten.concat((scale :d1, :major).to_a.flatten)

# Querying
puts (scale :c1,:major).to_a.flatten.include? 29
puts (scale :c1,:major).to_a.flatten.count 29

# Iterations
(scale :c1, :major).to_a.flatten.reverse_each {|i| puts i}

```

The addition of .to\_a.flatten appropriately sorts it out.

```ruby
puts scale :a1,:minor) => (ring <SonicPi::Scale :A :minor [33, 35, 36, 38, 40, 41, 43, 45])
puts scale( :a1, :minor).to_a => #<SonicPi::Scale :A :minor [33, 35, 36, 38, 40, 41, 43, 45]>
puts scale:a1, :minor).to_a.flatten. => [33, 35, 36, 38, 40, 41, 43, 45]

```

EDIT you can add .ring at the end if you want a ring as the final result.  
I’m not sure why the format of scale includes SonicPi::Scale, .flatten by itself removes this  
@samaaron might like to comment

---

<div class="post-metadata">

**Author:** ![enkerli](https://dub1.discourse-cdn.com/flex017/user_avatar/in-thread.sonic-pi.net/enkerli/32/54_2.png) [@enkerli](https://in-thread.sonic-pi.net/u/enkerli)\
**Post date:** [August 16, 2021, 10:21am UTC](https://in-thread.sonic-pi.net/t/shifting-rings-from-spread/2418/20 "2021-08-16T10:21:17Z")

</div>

Thanks!  
Also helping me grasp a few more features of rings.
