A Ruby range marks off values between endpoints. Its first job is answering whether a value falls inside it; when its values can be stepped through, it can also act as a collection. An integer range can be enumerated, but a range starting at one float and ending at another cannot. section 9.4
Choose the endpoint
`1..100` includes 100; `1...100` excludes it. `Range.new(1, 100)` is inclusive by default, while `Range.new(1, 100, true)` excludes the endpoint. An endless range such as `(1000...)` has no endpoint to include or exclude. Beginless ranges can still make that distinction: `(..1000)` includes 1000, and `(...1000)` does not. section 9.4.1
Use `begin` and `end` to inspect a range’s endpoints, and `exclude_end?` to check whether the ending value counts. Even `1...10` reports 10 as its `end`: exclusion changes the inclusion test, not the stored endpoint. section 9.4.2
Covered is not always included
For `r = "a".."z"`, `r.cover?("abc")` is true because `"abc"` compares between the endpoints. `r.include?("abc")` is false: the string range treats its members as the successive values from `"a"` through `"z"`. `member?` is another name for `include?`. Where a range cannot be treated as a finite collection, as with `1.0..2.0`, `include?` instead uses numerical comparison. section 9.4.2
Ranges also work as array and string slice positions: `['a','b','c','d'][0...-2]` returns `["a", "b"]`. For collection queries, `one?` and `none?` work on an integer range, but attempting `one?` on a float-starting range raises `TypeError`. A range can also serve as the criterion for `Enumerable#grep`: `[75, "hello", 10...20, "goodbye"].grep(50..100)` returns `[75]`. section 9.4.2 section 10.2 section 10.3.3







