# struct Range(B, E)

## Overview

A `Range` represents an interval: a set of values with a beginning and an end.

Ranges may be constructed using the usual `.new` method or with literals:

``````x..y  # an inclusive range, in mathematics: [x, y]
x...y # an exclusive range, in mathematics: [x, y)
(x..) # an endless range, in mathematics: >= x
..y   # a beginless inclusive range, in mathematics: <= y
...y  # a beginless exclusive range, in mathematics: < y``````

An easy way to remember which one is inclusive and which one is exclusive it to think of the extra dot as if it pushes y further away, thus leaving it outside of the range.

Ranges typically involve integers, but can be created using arbitrary objects as long as they define `succ` (or `pred` for `#reverse_each`), to get the next element in the range, and `<` and `==`, to know when the range reached the end:

``````# Represents a string of 'x's.
struct Xs
include Comparable(Xs)

getter size

def initialize(@size : Int32)
end

def succ
Xs.new(@size + 1)
end

def <=>(other)
@size <=> other.size
end

def inspect(io)
@size.times { io << 'x' }
end

def to_s(io)
io << @size << ' '
inspect(io)
end
end``````

An example of using `Xs` to construct a range:

``````r = Xs.new(3)..Xs.new(6)
r.to_s                 # => "xxx..xxxxxx"
r.to_a                 # => [Xs.new(3), Xs.new(4), Xs.new(5), Xs.new(6)]
r.includes?(Xs.new(5)) # => true``````

range.cr
range/bsearch.cr

## Instance Method Summary

• #===(value)

Same as `#includes?`, useful for the `case` expression.

• #begin : B

Returns the object that defines the beginning of this range.

• #bsearch(&block : B | E -> Bool)

By using binary search, returns the first value for which the passed block returns `true`.

• #clone

Returns a new `Range` with `#begin` and `#end` cloned.

• #covers?(value)

Same as `#includes?`.

• #cycle

Returns an `Iterator` that cycles over the values of this range.

• #each(&) : Nil

Iterates over the elements of this range, passing each in turn to the block.

• #each

Returns an `Iterator` over the elements of this range.

• #end : E

Returns the object that defines the end of the range.

• #excludes_end?

Returns `true` if this range excludes the end element.

• #exclusive? : Bool

Returns `true` if the range is exclusive.

• #includes?(value)

Returns `true` if this range includes the given value.

• #reverse_each(&) : Nil

Iterates over the elements of this range in reverse order, passing each in turn to the block.

• #reverse_each

Returns a reverse `Iterator` over the elements of this range.

• #step(by = 1)

Returns an `Iterator` that returns each nth element in this range.

• #step(by = 1, &)

Iterates over this range, passing each nth element to the block.

• #sum(initial)

If `self` is a `Int` range, it provides O(1) implementation, otherwise it is same as `Enumerable#sum`.

## Constructor Detail

def self.new(begin __arg0 : B, end __arg1 : E, exclusive : Bool = false) #

Constructs a `Range` using the given beginning and end.

``````Range.new(1, 10)                  # => 1..10
Range.new(1, 10, exclusive: true) # => 1...10``````

## Instance Method Detail

def ===(value) #

Same as `#includes?`, useful for the `case` expression.

``````case 79
when 1..50   then puts "low"
when 51..75  then puts "medium"
when 76..100 then puts "high"
end``````

Produces:

``high``

See also: `Object#===`.

def begin : B #

Returns the object that defines the beginning of this range.

``````(1..10).begin  # => 1
(1...10).begin # => 1``````

def bsearch(&block : B | E -> Bool) #

By using binary search, returns the first value for which the passed block returns `true`.

If the block returns `false`, the finding value exists behind. If the block returns `true`, the finding value is itself or exists infront.

``````(0..10).bsearch { |x| x >= 5 }                       # => 5
(0..Float64::INFINITY).bsearch { |x| x ** 4 >= 256 } # => 4``````

Returns `nil` if the block didn't return `true` for any value.

def clone #

Returns a new `Range` with `#begin` and `#end` cloned.

def covers?(value) #

Same as `#includes?`.

def cycle #

Returns an `Iterator` that cycles over the values of this range.

``(1..3).cycle.first(5).to_a # => [1, 2, 3, 1, 2]``

def each(&) : Nil #

Iterates over the elements of this range, passing each in turn to the block.

``````(10..15).each { |n| print n, ' ' }
# prints: 10 11 12 13 14 15``````

def each #

Returns an `Iterator` over the elements of this range.

``(1..3).each.skip(1).to_a # => [2, 3]``

def end : E #

Returns the object that defines the end of the range.

``````(1..10).end  # => 10
(1...10).end # => 10``````

def excludes_end? #

Returns `true` if this range excludes the end element.

``````(1..10).excludes_end?  # => false
(1...10).excludes_end? # => true``````

def exclusive? : Bool #

Returns `true` if the range is exclusive. Returns `false` otherwise (default).

def includes?(value) #

Returns `true` if this range includes the given value.

``````(1..10).includes?(4)  # => true
(1..10).includes?(10) # => true
(1..10).includes?(11) # => false

(1...10).includes?(9)  # => true
(1...10).includes?(10) # => false``````

def reverse_each(&) : Nil #

Iterates over the elements of this range in reverse order, passing each in turn to the block.

``````(10...15).reverse_each { |n| print n, ' ' }
# prints: 14 13 12 11 10``````

def reverse_each #

Returns a reverse `Iterator` over the elements of this range.

``(1..3).reverse_each.skip(1).to_a # => [2, 1]``

def step(by = 1) #

Returns an `Iterator` that returns each nth element in this range.

``(1..10).step(3).skip(1).to_a # => [4, 7, 10]``

def step(by = 1, &) #

Iterates over this range, passing each nth element to the block.

``````range = Xs.new(1)..Xs.new(10)
range.step(2) { |x| puts x }
puts
range.step(3) { |x| puts x }``````

Produces:

``````1 x
3 xxx
5 xxxxx
7 xxxxxxx
9 xxxxxxxxx

1 x
4 xxxx
7 xxxxxxx
10 xxxxxxxxxx``````

See `Range`'s overview for the definition of `Xs`.

def sum(initial) #

If `self` is a `Int` range, it provides O(1) implementation, otherwise it is same as `Enumerable#sum`.