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

Included Modules

Defined in:

range.cr
range/bsearch.cr

Constructors

Instance Method Summary

Instance methods inherited from module Iterable(B)

chunk(reuse = false, &block : T -> U) forall U chunk, chunk_while(reuse : Bool | Array(T) = false, &block : T, T -> B) forall B chunk_while, cycle(n)
cycle
cycle
, each each, each_cons(count : Int, reuse = false) each_cons, each_cons_pair each_cons_pair, each_slice(count : Int, reuse = false) each_slice, each_with_index(offset = 0) each_with_index, each_with_object(obj) each_with_object, slice_after(reuse : Bool | Array(T) = false, &block : T -> B) forall B
slice_after(pattern, reuse : Bool | Array(T) = false)
slice_after
, slice_before(reuse : Bool | Array(T) = false, &block : T -> B) forall B
slice_before(pattern, reuse : Bool | Array(T) = false)
slice_before
, slice_when(reuse : Bool | Array(T) = false, &block : T, T -> B) forall B slice_when

Instance methods inherited from module Enumerable(B)

accumulate(initial : U) : Array(U) forall U
accumulate : Array(T)
accumulate(initial : U, &block : U, T -> U) : Array(U) forall U
accumulate(&block : T, T -> T) : Array(T)
accumulate
, all?(& : T -> ) : Bool
all?(pattern) : Bool
all? : Bool
all?
, any?(& : T -> ) : Bool
any?(pattern) : Bool
any? : Bool
any?
, chunks(&block : T -> U) forall U chunks, compact_map(& : T -> _) compact_map, count(& : T -> ) : Int32
count(item) : Int32
count
, cycle(n, & : T -> ) : Nil
cycle(& : T -> ) : Nil
cycle
, each(& : T -> ) each, each_cons(count : Int, reuse = false, &) each_cons, each_cons_pair(& : T, T -> ) : Nil each_cons_pair, each_slice(count : Int, reuse = false, &) each_slice, each_with_index(offset = 0, &) each_with_index, each_with_object(obj : U, & : T, U -> ) : U forall U each_with_object, empty? : Bool empty?, find(if_none = nil, & : T -> ) find, find!(& : T -> ) : T find!, first(&)
first(count : Int) : Array(T)
first : T
first
, first? : T | Nil first?, flat_map(& : T -> _) flat_map, group_by(& : T -> U) forall U group_by, in_groups_of(size : Int, filled_up_with : U = nil) forall U
in_groups_of(size : Int, filled_up_with : U = nil, reuse = false, &) forall U
in_groups_of
, in_slices_of(size : Int) : Array(Array(T)) in_slices_of, includes?(obj) : Bool includes?, index(& : T -> ) : Int32 | Nil
index(obj) : Int32 | Nil
index
, index!(& : T -> ) : Int32
index!(obj) : Int32
index!
, index_by(& : T -> U) : Hash(U, T) forall U index_by, join(io : IO, separator = "") : Nil
join(separator, io : IO) : Nil
join(separator = "") : String
join(io : IO, separator = "", & : T, IO -> )
join(separator, io : IO, &)
join(separator = "", & : T -> )
join
, map(& : T -> U) : Array(U) forall U map, map_with_index(offset = 0, & : T, Int32 -> U) : Array(U) forall U map_with_index, max(count : Int) : Array(T)
max : T
max
, max? : T | Nil max?, max_by(& : T -> U) : T forall U max_by, max_by?(& : T -> U) : T | Nil forall U max_by?, max_of(& : T -> U) : U forall U max_of, max_of?(& : T -> U) : U | Nil forall U max_of?, min(count : Int) : Array(T)
min : T
min
, min? : T | Nil min?, min_by(& : T -> U) : T forall U min_by, min_by?(& : T -> U) : T | Nil forall U min_by?, min_of(& : T -> U) : U forall U min_of, min_of?(& : T -> U) : U | Nil forall U min_of?, minmax : Tuple(T, T) minmax, minmax? : Tuple(T | Nil, T | Nil) minmax?, minmax_by(& : T -> U) : Tuple(T, T) forall U minmax_by, minmax_by?(& : T -> U) : Tuple(T, T) | Tuple(Nil, Nil) forall U minmax_by?, minmax_of(& : T -> U) : Tuple(U, U) forall U minmax_of, minmax_of?(& : T -> U) : Tuple(U, U) | Tuple(Nil, Nil) forall U minmax_of?, none?(& : T -> ) : Bool
none?(pattern) : Bool
none? : Bool
none?
, one?(& : T -> ) : Bool
one?(pattern) : Bool
one? : Bool
one?
, partition(& : T -> ) : Tuple(Array(T), Array(T))
partition(type : U.class) forall U
partition
, product(initial : Number)
product
product(initial : Number, & : T -> )
product(& : T -> _)
product
, reduce(memo, &)
reduce(&)
reduce
, reduce?(&) reduce?, reject(& : T -> )
reject(type : U.class) forall U
reject(pattern) : Array(T)
reject
, sample(n : Int, random : Random = Random::DEFAULT) : Array(T)
sample(random : Random = Random::DEFAULT) : T
sample
, select(& : T -> )
select(type : U.class) : Array(U) forall U
select(pattern) : Array(T)
select
, size : Int32 size, skip(count : Int) skip, skip_while(& : T -> ) : Array(T) skip_while, sum(initial)
sum
sum(initial, & : T -> )
sum(& : T -> )
sum
, take_while(& : T -> ) : Array(T) take_while, tally(hash)
tally : Hash(T, Int32)
tally
, tally_by(hash, &)
tally_by(&block : T -> U) : Hash(U, Int32) forall U
tally_by
, to_a to_a, to_h
to_h(& : T -> Tuple(K, V)) forall K, V
to_h
, to_set : Set(T) to_set, zip(*others : Indexable | Iterable | Iterator, &)
zip(*others : Indexable | Iterable | Iterator)
zip
, zip?(*others : Indexable | Iterable | Iterator, &)
zip?(*others : Indexable | Iterable | Iterator)
zip?

Class methods inherited from module Enumerable(B)

element_type(x) element_type

Instance methods inherited from struct Struct

==(other) : Bool ==, hash(hasher) hash, inspect(io : IO) : Nil inspect, pretty_print(pp) : Nil pretty_print, to_s(io : IO) : Nil to_s

Instance methods inherited from struct Value

==(other : JSON::Any)
==(other : YAML::Any)
==(other)
==
, dup dup

Instance methods inherited from class Object

! : Bool !, !=(other) !=, !~(other) !~, ==(other) ==, ===(other : JSON::Any)
===(other : YAML::Any)
===(other)
===
, =~(other) =~, as(type : Class) as, as?(type : Class) as?, class class, dup dup, hash(hasher)
hash
hash
, in?(collection : Object) : Bool
in?(*values : Object) : Bool
in?
, inspect(io : IO) : Nil
inspect : String
inspect
, is_a?(type : Class) : Bool is_a?, itself itself, nil? : Bool nil?, not_nil!(message)
not_nil!
not_nil!
, pretty_inspect(width = 79, newline = "\n", indent = 0) : String pretty_inspect, pretty_print(pp : PrettyPrint) : Nil pretty_print, responds_to?(name : Symbol) : Bool responds_to?, tap(&) tap, to_json(io : IO) : Nil
to_json : String
to_json
, to_pretty_json(indent : String = " ") : String
to_pretty_json(io : IO, indent : String = " ") : Nil
to_pretty_json
, to_s(io : IO) : Nil
to_s : String
to_s
, to_yaml(io : IO) : Nil
to_yaml : String
to_yaml
, try(&) try, unsafe_as(type : T.class) forall T unsafe_as

Class methods inherited from class Object

from_json(string_or_io, root : String)
from_json(string_or_io)
from_json
, from_yaml(string_or_io : String | IO) from_yaml

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

[View source]

Instance Method Detail

def ==(other : Range) #

[View source]
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#===.


[View source]
def begin : B #

Returns the object that defines the beginning of this range.

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

[View source]
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

[View source]
def clone #

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


[View source]
def covers?(value) #

Same as #includes?.


[View source]
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]

[View source]
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

[View source]
def each #

Returns an Iterator over the elements of this range.

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

[View source]
def end : E #

Returns the object that defines the end of the range.

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

[View source]
def excludes_end? : Bool #

Returns true if this range excludes the end element.

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

[View source]
def exclusive? : Bool #

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


[View source]
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

[View source]
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)"

[View source]
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]

[View source]
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

[View source]
def reverse_each #

Returns a reverse Iterator over the elements of this range.

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

[View source]
def sample(random : 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.


[View source]
def sample(n : Int, random = Random::DEFAULT) #

:inherit:

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.


[View source]
def size #

Returns the number of values in this range.

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

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

[View source]
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.


[View source]
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.


[View source]
def sum(initial) #

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


[View source]
def to_s(io : IO) : Nil #
Description copied from struct Struct

Same as #inspect(io).


[View source]