Project

General

Profile

Actions

Feature #14777

open

Add Range#offset ?

Added by owst (Owen Stephens) about 3 years ago. Updated about 3 years ago.

Status:
Open
Priority:
Normal
Assignee:
-
Target version:
-
[ruby-core:87190]

Description

Hi,

As mentioned in https://bugs.ruby-lang.org/issues/14473#note-17 an addition to Range that we find useful is an Range#offset(n) method that adds (or subtracts) n to the range, for example:

(1..10).offset(2)   # => (3..12)
(1...10).offset(1)  # => (2...11)
(1..10).offset(-10) # => (-9..0)

Similarly to Range#step we can support non-Numeric objects if they implement succ:

('a'..'e').offset(2) # => ('c'..'g')

Alternative names could be Range#shift (i.e. shift the elements of the Range up or down) or perhaps >>/<<:

(1..10).shift(2) # => (3..12)
(1..10) >> 2 # => (3..12)
(1...10) << 1 # => (0...9)

However, I don't think the operators are clear enough, so I prefer offset or shift.

An example pure Ruby implementation is:

class Range
  def offset(n)
    add_n = ->(x) do
      if x.is_a?(Numeric)
        x + n
      elsif x.respond_to?(:succ)
        n.times { x = x.succ }
        x
      else
        raise ArgumentError, "Can't offset #{x.class}"
      end
    end

    if exclude_end?
      (add_n.call(first)...add_n.call(last))
    else
      (add_n.call(first)..add_n.call(last))
    end
  end
end

Please let me know your thoughts, I can then look to implement this properly in C.

Regards,
Owen.

Actions

Also available in: Atom PDF