/Crystal

# 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

## Constructor Detail

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

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)Source

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

### def begin : BSource

Returns the object that defines the beginning of this range.

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

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

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 cloneSource

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

### def covers?(value)Source

Same as #includes?.

### def cycleSource

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(&) : NilSource

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 eachSource

Returns an Iterator over the elements of this range.

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

### def end : ESource

Returns the object that defines the end of the range.

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

### def excludes_end?Source

Returns true if this range excludes the end element.

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

### def exclusive? : BoolSource

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

### def includes?(value)Source

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(&) : NilSource

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_eachSource

Returns a reverse Iterator over the elements of this range.

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

### def step(by = 1)Source

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, &)Source

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)Source

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