Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ruby Range Unexpected Behavior

Tags:

range

ruby

Can anyone shed some insight onto why the following happens?

irb(main):001:0> r = '1'..'30'
=> "1".."30"
irb(main):002:0> r.each do |i|
irb(main):003:1* puts "#{i} : #{r.include?(i)}"
irb(main):004:1> end
1 : true
2 : true
3 : true
4 : false
5 : false
6 : false
7 : false
8 : false
9 : false
10 : true
...
(snip.. the String-numbers here evaluate to true)
...
29 : true
30 : true
=> "1".."30"

I'd expect the above to be all trues. If I do the following:

irb(main):005:0> r.to_a.each do |i|
irb(main):006:1* puts "#{i} : #{r.to_a.include?(i)}"
irb(main):007:1> end
1 : true
2 : true
...
(snip.. the String-numbers here evaluate to true)
...
29 : true
30 : true
=> ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "
15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28
", "29", "30"]

then I get what I expected. Am I missing something with how ranges work or could this be a bug (probably the former)? My bad in advance if this is a noob question. Hard/soft quoting doesn't make a difference, and the same problem happens with ranges of numbers in String-form for values other than between 1 to 30.

like image 703
maksim Avatar asked Jan 23 '23 06:01

maksim


1 Answers

This is a quirk of how ranges work in Ruby. The objects are generated by repeatedly calling succ, but membership is determined by x >= r.start && x <= r.end. Strings in Ruby do not have special behavior for ordering numbers — '4' is greater than '10' because '4' is greater than '1'. So any single-digit numbers that are higher than the first digit of the end value will appear not to be in range.

like image 78
Chuck Avatar answered Jan 28 '23 15:01

Chuck