Difference between '..' (double-dot) and '...' (triple-dot) in range generation?
The documentation for Range† says this:
Ranges constructed using
..
run from the beginning to the end inclusively. Those created using...
exclude the end value.
So a..b
is like a <= x <= b
, whereas a...b
is like a <= x < b
.
Note that, while to_a
on a Range of integers gives a collection of integers, a Range is not a set of values, but simply a pair of start/end values:
(1..5).include?(5) #=> true(1...5).include?(5) #=> false(1..4).include?(4.1) #=> false(1...5).include?(4.1) #=> true(1..4).to_a == (1...5).to_a #=> true(1..4) == (1...5) #=> false
†The docs used to not include this, instead requiring reading the Pickaxe’s section on Ranges. Thanks to @MarkAmery (see below) for noting this update.
The API docs now describe this behaviour:
Ranges constructed using
..
run from the beginning to the end inclusively. Those created using...
exclude the end value.
In other words:
2.1.3 :001 > ('a'...'d').to_a => ["a", "b", "c"] 2.1.3 :002 > ('a'..'d').to_a => ["a", "b", "c", "d"]