Class Interval
In: lib/facets/supplemental/facets/interval.rb
Parent: Object

Interval

While Ruby support the Range class out of the box, is does not quite fullfil the role od a real Interval class. For instance, it does not support excluding the front sentinel. This is because Range also tries to do triple duty as a simple Sequence and as a simple Tuple-Pair, thus limiting its potential as an Interval. The Interval class remedies the situation by commiting to interval behavior, and then extends the class’ capabilites beyond that of the standard Range in ways that naturally fall out of that.

Range depends on two methods: succ and #<=>. If numeric ranges were the only concern, those could just as well be #+ and #<=>, but esoteric forms make that unfeasible —the obvious example being a String range. But a proper Interval class requires mathematical continuation, thus the Interval depends on #+ and #<=>, as well as #- as the inverse of #+.

  i = Interval.new(1,5)
  i.to_a       #=> [1,2,3,4,5]

  i = Interval[0,5]
  i.to_a(2)    #=> [0,2,4]

  i = Interval[1,5]
  i.to_a(-1)   #=> [5,4,3,2,1]

  i = Interval[1,3]
  i.to_a(1,2)  #=> [1.0,1.5,2.0,2.5,3.0]

Methods

+@   -@   ===   []   begin   closed   degenerate?   direction   distance   each   end   eql?   exclude_begin?   exclude_end?   exclude_first?   exclude_last?   first   first_closed   first_opened   half_closed   include?   last   last_closed   last_opened   length   max   member?   min   new   null?   opened   reversed   sentinels   size   step   ~  

Included Modules

Multiton Enumerable::Arguments

Public Class methods

[Source]

# File lib/facets/supplemental/facets/interval.rb, line 90
  def self.[]( *args )
    self.new( *args )
  end

[Source]

# File lib/facets/supplemental/facets/interval.rb, line 95
  def initialize(first, last, exclude_first=false, exclude_last=false )
    raise ArgumentError, "bad value for interval" if first.class != last.class
    @first = first
    @last = last
    @exclude_first = exclude_first
    @exclude_last = exclude_last
    @direction = (@last <=> @first)
  end

Public Instance methods

Unary shorthands. These return a new interval exclusive of first, last or both sentinels, repectively.

[Source]

# File lib/facets/supplemental/facets/interval.rb, line 161
  def +@ ; Interval.new(first, last, true, false) ; end

[Source]

# File lib/facets/supplemental/facets/interval.rb, line 162
  def -@ ; Interval.new(first, last, false, true) ; end
===(x)

Alias for include?

begin()

Alias for first

Returns a new interval inclusive of of both sentinels.

[Source]

# File lib/facets/supplemental/facets/interval.rb, line 141
  def closed; Interval.new(@first, @last, true, true) ; end

Returns true if the start and end sentinels are equal and the interval is closed; otherwise false.

[Source]

# File lib/facets/supplemental/facets/interval.rb, line 127
  def degenerate? ; @direction == 0 and ! (@exclusive_first or @exclusive_last) ;  end

Returns the direction of the interval indicated by +1, 0 or -1.

  (1..5).direction  #=> 1
  (5..1).direction  #=> -1
  (1..1).direction  #=> 0

[Source]

# File lib/facets/supplemental/facets/interval.rb, line 138
  def direction ; @direction ; end

Returns the length of the interval as the difference between the first and last elements. Returns nil if the sentinal objects do not support distance comparison (distance). TODO: Add n parameter to count segmentations like those produced by each.

[Source]

# File lib/facets/supplemental/facets/interval.rb, line 177
  def distance
    @last - @first
    #if @last.respond_to?( :distance )
    #  @last.distance( @first )
    #else
    #  #self.to_a.length
    #end
  end

Iterates over the interval, passing each _n_th element to the block. If n is not given then n defaults to 1. Each _n_th step is determined by invoking +++ or +\-+ n, depending on the direction of the interval. If n is negative the iteration is preformed in reverse form end sentinal to front sentinal. A second parameter, d, can be given in which case the applied step is calculated as a fraction of the interval‘s length times n / d. This allows iteration over the whole interval in equal sized segments.

  1..5.each { |e| ... }        #=> 1 2 3 4 5
  1..5.each(2) { |e| ... }     #=> 1 3 5
  1..5.each(1,2) { |e| ... }   #=> 1.0 1.5 2.0 2.5 3.0 3.5 4.0 4.5 5.0

[Source]

# File lib/facets/supplemental/facets/interval.rb, line 241
  def each(n=1, d=nil)  # :yield:
    return (n < 0 ? @last : @first) if degenerate?  # is this right for all values of n ?
    s = d ? self.length.to_f * (n.to_f / d.to_f) : n.abs
    raise "Cannot iterate over zero length steps." if s == 0
    s = s * @direction
    if n < 0
      e = @exclude_last ? @last - s : @last
      #e = @exclude_last ? @last.pred(s) : @last
      t = @exclude_last ? 1 : 0
      #while e.cmp(@first) >= t
      while (e <=> @first) >= t
        yield(e)
        e -= s
        #e = e.pred(s)
      end
    else
      e = @exclude_first ? @first + s : @first
      #e = @exclude_first ? @first.succ(s) : @first
      t = @exclude_last ? -1 : 0
      #while e.cmp(@last) <= t
      while (e <=> @last) <= t
        yield(e)
        e += s
        #e = e.succ(s)
      end
    end
  end
end()

Alias for last

Compares two intervals to see if they are equal

[Source]

# File lib/facets/supplemental/facets/interval.rb, line 276
  def eql?(other)
    return false unless @first == other.first
    return false unless @last == other.last
    return false unless @exclude_first == other.exclude_first?
    return false unless @exclude_last == other.exclude_last?
    true
  end
exclude_begin?()

Alias for exclude_first?

exclude_end?()

Alias for exclude_last?

[Source]

# File lib/facets/supplemental/facets/interval.rb, line 117
  def exclude_first? ; @exclude_first ; end

[Source]

# File lib/facets/supplemental/facets/interval.rb, line 118
  def exclude_last? ; @exclude_last ; end

Returns the first or last sentinal of the interval.

[Source]

# File lib/facets/supplemental/facets/interval.rb, line 113
  def first ; @first ; end

Returns a new interval with one of the two sentinels opened or closed

[Source]

# File lib/facets/supplemental/facets/interval.rb, line 154
  def first_closed ; Interval.new(@first, @last, false, true) ; end

[Source]

# File lib/facets/supplemental/facets/interval.rb, line 156
  def first_opened ; Interval.new(@first, @last, true, false) ; end

Returns a new interval with either the first or the last sentinel exclusive. If the parameter is false, the deafult, then the first sentinel is excluded; if the parameter is true, the last sentinel is excluded.

[Source]

# File lib/facets/supplemental/facets/interval.rb, line 149
  def half_closed(e=false)
    e ? Interval.new(@first, @last, true, false) : Interval.new(@first, @last, false, true)
  end

Returns true or false if the element is part of the interval.

[Source]

# File lib/facets/supplemental/facets/interval.rb, line 199
  def include?(x)
    # todo: infinity?
    tf = exclude_first? ? 1 : 0
    tl = exclude_last? ? -1 : 0
    (x <=> first) >= tf and (x <=> last) <= tl
  end

[Source]

# File lib/facets/supplemental/facets/interval.rb, line 114
  def last ; @last ; end

[Source]

# File lib/facets/supplemental/facets/interval.rb, line 155
  def last_closed ; Interval.new(@first, @last, true, false) ; end

[Source]

# File lib/facets/supplemental/facets/interval.rb, line 157
  def last_opened ; Interval.new(@first, @last, false, true) ; end
length()

Alias for distance

Returns the greater of the first and last sentinals.

[Source]

# File lib/facets/supplemental/facets/interval.rb, line 194
  def max
    ((@first <=> @last) == 1) ? @first : @last
  end
member?(x)

Alias for include?

Returns the lesser of the first and last sentinals.

[Source]

# File lib/facets/supplemental/facets/interval.rb, line 189
  def min
    ((@first <=> @last) == -1) ? @first : @last
  end

Returns true if the start and end sentinels are equal and the interval is open; otherwise false.

[Source]

# File lib/facets/supplemental/facets/interval.rb, line 130
  def null? ; @direction == 0 and @exclusive_first and @exclusive_last ; end

Returns a new interval exclusive of both sentinels.

[Source]

# File lib/facets/supplemental/facets/interval.rb, line 144
  def opened; Interval.new(@first, @last, true, true) ; end

Returns a new interval with the sentinels reversed.

  (0..10).reversed  #=> 10..0

[Source]

# File lib/facets/supplemental/facets/interval.rb, line 169
  def reversed
    Interval.new(@last, @first, true, true)
  end

Returns a two element array of first and last sentinels.

 (0..10).sentinels   #=> [0,10]

[Source]

# File lib/facets/supplemental/facets/interval.rb, line 108
  def sentinels
    return [@first, @last]
  end
size()

Alias for distance

step(n=1, d=nil)

Alias for each

[Source]

# File lib/facets/supplemental/facets/interval.rb, line 163
  def ~@ ; Interval.new(first, last, true, true) ; end

[Validate]