# Ruby .. range problem?

**URL:** <https://in-thread.sonic-pi.net/t/ruby-range-problem/7280>\
**Category:** Support, Help & Resources\
**Created:** [November 19, 2022, 3:25am UTC](https://in-thread.sonic-pi.net/t/ruby-range-problem/7280 "2022-11-19T03:25:06Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![Buce](https://avatars.discourse-cdn.com/v4/letter/b/e5b9ba/32.png) [@Buce](https://in-thread.sonic-pi.net/u/Buce)\
**Post date:** [November 19, 2022, 3:25am UTC](https://in-thread.sonic-pi.net/t/ruby-range-problem/7280/1 "2022-11-19T03:25:06Z")

</div>

There seems te be a problem with the to me intuitive ruby `..` range.  
I tried  
`puts (:c..:fs6).to_a`  
but it shows nothing in the protocol.

I tried this on a windows 10 laptop with SPI4.3.  
I expected to see something in the protocol.

I got curious when I executed in SPI4.3  
`play (:c..:fs6).to_a.choose`  
and got

```ruby
Runtime Error: [buffer 5, line 1] - SonicPi::Note::InvalidNoteError
Thread death!
Invalid note: :tgi

```

and with  
`play (:c..:fs6).to_a`  
I got  
`Invalid note: :h`  
and with  
`play :c..:fs6`  
i got no sound although i would expect the same sound as with  
`play range :c,:fs6`

This seems to be similar in SPI3.3.1?

And problems certainly apply to other symbolic notes combinations like

`play :c6..:e6` → no sound … bad … unexpected … is it a system failure?

compared to some sound with:

`play range :c6,:e6` → expected little higher sound than `play range :c,:fs6`

And all this has nothing especially to do with symbolic notes  
but with the intuitive ruby `..` range.  
Because the same problems arise with integer numbers like:  
`play 60..90` → no sound … in my opinion a system failure!!  
`play range 60,90` → some sound … OK!!

I mean I am a kind of nitpicking and very much prefer a SPI with  
many simple intuitive ways to express musical ideas.

And in my opinion `6..79` is simpler and little bit more intuitive  
than `range 6,79`.

---

<div class="post-metadata">

**Author:** ![Buce](https://avatars.discourse-cdn.com/v4/letter/b/e5b9ba/32.png) [@Buce](https://in-thread.sonic-pi.net/u/Buce)\
**Post date:** [November 22, 2022, 7:18pm UTC](https://in-thread.sonic-pi.net/t/ruby-range-problem/7280/4 "2022-11-22T19:18:19Z")

</div>

> [@Ruby Symbols in SPi](https://in-thread.sonic-pi.net/t/ruby-symbols-in-spi/4607/4):
>
> calls like `to_s` and `to_f` are really not supported and you shouldn’t assume they’ll always be available and/or produce the same behaviour across versions.

But will `.to_a` be supported?

Or what is the SPI way planned to convert something into an array?

---

<div class="post-metadata">

**Author:** ![emlyn](https://dub1.discourse-cdn.com/flex017/user_avatar/in-thread.sonic-pi.net/emlyn/32/1460_2.png) [@emlyn](https://in-thread.sonic-pi.net/u/emlyn)\
**Post date:** [November 23, 2022, 10:33am UTC](https://in-thread.sonic-pi.net/t/ruby-range-problem/7280/5 "2022-11-23T10:33:40Z")

</div>

> [@Buce](#):
>
> what is the SPI way planned to convert something into an array?

What is the use case where an array is required that wouldn’t be satisfied by a Sonic Pi ring?

---

<div class="post-metadata">

**Author:** ![Buce](https://avatars.discourse-cdn.com/v4/letter/b/e5b9ba/32.png) [@Buce](https://in-thread.sonic-pi.net/u/Buce)\
**Post date:** [November 23, 2022, 7:31pm UTC](https://in-thread.sonic-pi.net/t/ruby-range-problem/7280/6 "2022-11-23T19:31:46Z")

</div>

Rings are frozen structures in Sonic Pi.  
If I want to change just a single element of a large  
array I can do it.

For rings I had to recreate or compose another ring.

Also only rotating activities need rings.  
Just choosing so randomized activities do not need rings.

I hear the first time that Sonic Pi plans only to use rings in future.

So how I can do the following easily:

```ruby
mchord = (chord :c3, :m7)
#mchord = (chord :c3, :m7).to_a # only this works

play mchord
sleep 1
mchord[2]=67 # adapting my chord

play mchord

```

---

<div class="post-metadata">

**Author:** ![emlyn](https://dub1.discourse-cdn.com/flex017/user_avatar/in-thread.sonic-pi.net/emlyn/32/1460_2.png) [@emlyn](https://in-thread.sonic-pi.net/u/emlyn)\
**Post date:** [November 24, 2022, 10:44am UTC](https://in-thread.sonic-pi.net/t/ruby-range-problem/7280/7 "2022-11-24T10:44:59Z")

</div>

You could define a helper to update individual values in a collection, maybe something like:

```ruby
define :update do |coll, index, val|
  coll[0..index] + [val] + coll[index+1..coll.size]
end

mchord = (chord :c3, :m7)

puts mchord
play mchord

sleep 1

mchord = update(mchord, 2, 67) # adapting my chord

puts mchord
play mchord

```

I’m not convinced that a new data structure is necessary, but I think it would be nice to have something like that function built in to Sonic Pi.

---

<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:** [November 25, 2022, 1:41pm UTC](https://in-thread.sonic-pi.net/t/ruby-range-problem/7280/8 "2022-11-25T13:41:44Z")

</div>

Please note that Ruby’s `..` range syntax is not formally supported by Sonic Pi. Whilst it should work as expected in most cases, it can’t be relied upon to continue working for future versions of Sonic Pi. Additionally, supporting ranges of notes isn’t completely obvious to me how it would make sense musically as it would always work over the chromatic scale.

---

<div class="post-metadata">

**Author:** ![Buce](https://avatars.discourse-cdn.com/v4/letter/b/e5b9ba/32.png) [@Buce](https://in-thread.sonic-pi.net/u/Buce)\
**Post date:** [December 3, 2022, 1:54pm UTC](https://in-thread.sonic-pi.net/t/ruby-range-problem/7280/9 "2022-12-03T13:54:02Z")

</div>

As I mentioned to my perception `a..b` is a simple intuitive syntax.

And actually how possibly could I know that this is ruby syntax only?

It is really hard to differentiate in a just tutorial documentation  
and the mentioning that Sonic Pi is on top of Ruby  
what is or will possibly be allowed in a future Sonic Pi.

I do not see any section discussing arithmetic for example.

You probably do not plan to convert to an agressive functional  
style and we would need to write `add 4, 5` in future to add two numbers,  
do you?

So what arithmetic is allowed in Sonic PI and what arithmetic should be avoided?

Everywhere it is used but nowhere mentioned explicitly in the tutorial.

Is there a Sonic Pi syntax description available?

What of the following arithmetic ‘is’/will be allowed?  
(All are possible currently.)

```ruby
# program to illustrate
# Arithmetic operations

a = 2.1
b = 2

# Addition
c = a + b

puts "addition #{c}"

# Subtraction
d = a - b

puts "subtraction #{d}"

# Multiplication
e = a * b

puts "multiplication #{e}"

# Division
f = a / b

puts "division #{f}"

# integer division

puts "integer division(i.e. 3/4==0): #{3/4}"

# Modulo
g = a % b

puts "modulo #{g}"

# .divmod Method

g = a.divmod(b)
puts "divmod #{g}"

puts (45.0.divmod 5)
puts (98.0.divmod 5)

# Exponent
h = a ** b

puts "exponent #{h}"

# Unary minus
i= -a

puts "unary minus #{i}"

# float-comparison <=> Method

puts 2.1 <=> 4
puts 2.0 <=> 2
puts 4.6 <=> 2

# == Method (equals 1)
puts 3.8 == 4
puts 3.8 == 3.8

# === Method (equals 2)
puts 3.8 === 4
puts 3.8 === 3.8

# .eql Method (equals 3)
puts 4.2.eql?(2)
puts 1.2.eql?(1.2)

# .eqlual Method (equals 4)
a = 'xyz'
b = "xyz"

puts a.equal? b
puts 1.2.equal? 1.2

# .zero? Method
puts (0.0).zero?
puts (1.4).zero?

# .nan? Method
puts (-2.2). nan?
puts (0.0/0.0). nan?

# .abs Method
puts (-54.56).abs
puts (-65.04).abs

# .ceil Method
puts (4.1).ceil
puts (4.0).ceil
puts (-4.1).ceil

# .floor Method
puts 2.2. floor
puts (-4.6).floor

# finite? Method
puts (45.0).finite?
puts (45.0/0.0).finite?

# .infinite? Method
puts (1.1).infinite?
puts (-1.1/0.0).infinite?
puts (+1.1/0.0).infinite?

# .modulo(number) Method
puts 32.45.modulo(20)

# .round Method
puts 5.673.round

# .round(digtis) Method
puts 5.673.round(2)

# .to_f Method
puts 'x'.to_f
puts 5.to_f

# float.to_i Method
puts 5.673.to_i
# float.to_int Method
puts 5.673.to_int
# float.truncate Method
puts 5.673.truncate

```

And which other Operators  
[Ruby - Operators (tutorialspoint.com)](https://www.tutorialspoint.com/ruby/ruby_operators.htm)  
i.e.:

```ruby
* # Splat Operator
<< # Shovel / Push Operator ?
=~ / !~ # Matching / Not Matching Operator
?: # Ternary Operator

```

etc. are probably supported?

---

<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:** [December 5, 2022, 12:16pm UTC](https://in-thread.sonic-pi.net/t/ruby-range-problem/7280/10 "2022-12-05T12:16:32Z")

</div>

Hi there,

just to be clear, there is nothing stopping you from using any Ruby functionality in your Sonic Pi code. Nothing is out of bounds - I absolutely encourage you to experiment and play.

However, from a practical perspective, Sonic Pi is mini language built on top of Ruby. This means some aspects of Ruby were modified and used in a non-standard way in order to make the Sonic Pi experience what it is. Sonic Pi currently does not have a formal specification and it’s not something I’m interested in spending the time to work on because I’m more interested in finding ways to improve the general experience and functionality for everyone rather than to painstakingly attempt to define all the possible edge cases where the interaction between Sonic Pi’s mini language and vanilla Ruby conflict.

In lieu of a formal specification, the tutorial currently stands as the best document to describe what functionality was intended. By intended, I mean functionality that was designed and tested to work as documented. I have also promised to try my best to specify in the changelogs where this functionality has changed between releases. I do not have the resources to document where any arbitrary Ruby functionality may break or change between release - this I what I’m specifically referring to when I talk about “supported”. It’s more of a friendly promise from me to all users that I’ll let you know when things change or are removed than a formal specification.

At some point I’m planning to move the core implementation to Elixir at which point a more formal spec may be feasible but be warned, if such a thing were to exist it will be a _tiny_ subset of the various accidentally inherited functionality of the current Ruby DSL.

Sonic Pi isn’t intended to be a fully fledged programming language that you can use to build websites, work with AI / robotics, do numerical calculations, etc. Its goal is to be a simple yet powerful musical instrument. Simple enough to teach introductory computer science and powerful enough for professional musicians.

---

<div class="post-metadata">

**Author:** ![jonny](https://avatars.discourse-cdn.com/v4/letter/j/47e85d/32.png) [@jonny](https://in-thread.sonic-pi.net/u/jonny)\
**Post date:** [September 16, 2023, 9:14pm UTC](https://in-thread.sonic-pi.net/t/ruby-range-problem/7280/11 "2023-09-16T21:14:35Z")

</div>

Hi, good question!

Not sure if still helpful, but I just had a pop and found

- arrays and ranges work as expected in ruby.sp

```ruby
a = (1..3)
a.each {|n| puts n}

```

- converting these symbols to ints is a doddle, and for readability the range can be spaced

```ruby
b = (:c1.to_i .. :d4.to_i)
puts b

```

hope that makes sense and helps !
