# 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``````

See `Range` literals in the language reference.

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

• #==(other : Range)
• #===(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 -> _)

By using binary search, returns the first element for which the passed block returns a truthy value.

• #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? : Bool

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

• #exclusive? : Bool

Returns `true` if the range is exclusive.

• #includes?(value) : Bool

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

• #inspect(io : IO) : Nil

Appends this struct's name and instance variables names and values to the given IO.

• #map(&block : B -> U) forall U

Returns an `Array` with the results of running the block against each element of the collection.

• #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.

• #sample(n : Int, random = Random::DEFAULT)

Returns an `Array` of n random elements from `self`, using the given random number generator.

• #sample(random = Random::DEFAULT)

Optimized version of `Enumerable#sample` that runs in O(1) time when `self` is an `Int` or `Float` range.

• #size

Returns the number of values in this range.

• #step(by = 1, &) : Nil

Iterates from `#begin` to `#end` incrementing by the amount of step on each iteration.

• #step(by = 1) : Iterator

Iterates from `#begin` to `#end` incrementing by the amount of step on each iteration.

• #sum(initial)

Optimized version of `Enumerable#sum` that runs in O(1) time when `self` is an `Int` range.

• #to_s(io : IO) : Nil

Same as `#inspect(io)`.

## 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 ==(other : Range) #

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 -> _) #

By using binary search, returns the first element for which the passed block returns a truthy value.

If the block returns a falsey value, the element to be found lies behind. If the block returns a truthy value, the element to be found is itself or lies in front.

Returns `nil` if the block didn't return a truthy value for any element.

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

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? : Bool #

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) : Bool #

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 inspect(io : IO) : Nil #
Description copied from struct Struct

Appends this struct's name and instance variables names and values to the given IO.

``````struct Point
def initialize(@x : Int32, @y : Int32)
end
end

p1 = Point.new 1, 2
p1.to_s    # "Point(@x=1, @y=2)"
p1.inspect # "Point(@x=1, @y=2)"``````

def map(&block : B -> U) forall U #
Description copied from module Enumerable(B)

Returns an `Array` with the results of running the block against each element of the collection.

``[1, 2, 3].map { |i| i * 10 } # => [10, 20, 30]``

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 sample(n : Int, random = Random::DEFAULT) #

Returns an `Array` of n random elements from `self`, using the given random number generator. All elements have equal probability of being drawn. Sampling is done without replacement; if n is larger than the size of this collection, the returned `Array` has the same size as `self`.

Raises `ArgumentError` if n is negative.

``````[1, 2, 3, 4, 5].sample(2)                # => [3, 5]
{1, 2, 3, 4, 5}.sample(2)                # => [3, 4]
{1, 2, 3, 4, 5}.sample(2, Random.new(1)) # => [1, 5]``````

If `self` is not empty and `n` is equal to 1, calls `#sample(random)` exactly once. Thus, random will be left in a different state compared to the implementation in `Enumerable`.

def sample(random = Random::DEFAULT) #

Optimized version of `Enumerable#sample` that runs in O(1) time when `self` is an `Int` or `Float` range. In these cases, this range is considered to be a distribution of numeric values rather than a collection of elements, and the method simply calls `random.rand(self)`.

Raises `ArgumentError` if `self` is an open range.

def size #

Returns the number of values in this range.

If both the beginning and the end of this range are `Int`s, runs in constant time instead of linear.

``````(3..8).size  # => 5
(3...8).size # => 6``````

def step(by = 1, &) : Nil #

Iterates from `#begin` to `#end` incrementing by the amount of step on each iteration.

``````ary = [] of Int32
(1..4).step(by: 2) do |x|
ary << x
end
ary                      # => [1, 3]
(1..4).step(by: 2).to_a  # => [1, 3]
(1..4).step(by: 1).to_a  # => [1, 2, 3, 4]
(1...4).step(by: 1).to_a # => [1, 2, 3]``````

If `B` is a `Steppable`, implementation is delegated to `Steppable#step`. Otherwise `#succ` method is expected to be defined on `#begin` and its successors and iteration is based on calling `#succ` sequentially (step times per iteration).

Raises `ArgumentError` if `#begin` is `nil`.

def step(by = 1) : Iterator #

Iterates from `#begin` to `#end` incrementing by the amount of step on each iteration.

``````ary = [] of Int32
(1..4).step(by: 2) do |x|
ary << x
end
ary                      # => [1, 3]
(1..4).step(by: 2).to_a  # => [1, 3]
(1..4).step(by: 1).to_a  # => [1, 2, 3, 4]
(1...4).step(by: 1).to_a # => [1, 2, 3]``````

If `B` is a `Steppable`, implementation is delegated to `Steppable#step`. Otherwise `#succ` method is expected to be defined on `#begin` and its successors and iteration is based on calling `#succ` sequentially (step times per iteration).

Raises `ArgumentError` if `#begin` is `nil`.

def sum(initial) #

Optimized version of `Enumerable#sum` that runs in O(1) time when `self` is an `Int` range.

def to_s(io : IO) : Nil #
Description copied from struct Struct

Same as `#inspect(io)`.