Issue #7545 has been updated by drbrain (Eric Hodel).


alexeymuranov (Alexey Muranov) wrote:
> But it is not a set, it seems to be just a pair of bounds, like a 2-element array. I propose to change the semantics, and hence behavior in applications like `Array#slice`.

How is this beneficial to Rubyists?

> > If no bounds are stored for an empty set and you can't tell the difference between (1???1) and (3???3) what should Range#inspect do?
> 
> Just print that it is the empty range.  I suggested a constant name `Range::EMPTY_SET`

These don't seem useful:

p (1???1) #=> Range::EMPTY_SET
p (3???3) #=> Range::EMPTY_SET
p ('a'???'b') #=> Range::EMPTY_SET

I can't think of any other built-in class that behaves this way.

Discarding the beginning and ending of the Range is very distasteful. I don't approve.

> > What is an ambient set?
> 
> I meant that to store 1..3 or 3..1 or 1...(3.5), it is enough to store the bounds, assume that the the interval is a subset of the reals (so that floats, rationals, and others could be tested for inclusion,  for 'a'..'c' the natural ambient set would be the set of words), and remember the order (the usual or the reverse).

Range already stores only the bounds.  For Numeric bounds, Range#include? and Range#cover? already assume the interval is a subset of the reals (with the exception that the lower bound must be the lower number).

Can you show value for allowing the lower bound to be the higher number?

> > Why is such a big change necessary?
> 
> This would make the Range class quite intelligent.  I do not know if it is necessary.

Since you do not know if it is necessary I think this should be rejected.

> > Range and Set are different concepts (and classes). I don't see why you would define equality on Set based on some other class (Array, here). This is not good OO design.
> 
> `Set` class only works to store finite sets, while `Range` class can be used to represent infinite sets, like the intervals [0, ???), or [0, 1] (there are infinitely many reals or rationals in both).

As I stated above, no change to ruby is necessary.

p (1...Float::INFINITY).include? Float::INFINITY #=> false
p (0..1).include? 0.5 #=> true

> For the equality of 1...1 and 3...3, i meant that they both model the same object: the empty set, this was the actual reason.

Purposeful information loss is a bad policy, I think this proposal should be rejected.

> > > I did not talk about `#cover?` in this proposal, but in my opinion having both is redundant, i would prefer having just `#include?`, possibly with some options.
> > 
> > How does this fit with existing implementations of #include?
> 
> I do not know. I was thinking about an abstraction of `Range` class.

Since you do not know, I think this proposal should be rejected.
----------------------------------------
Feature #7545: Make Range act as a "lazy ordered set"
https://bugs.ruby-lang.org/issues/7545#change-34638

Author: alexeymuranov (Alexey Muranov)
Status: Open
Priority: Normal
Assignee: 
Category: core
Target version: Next Major


=begin
# Make Range act as a "lazy ordered set"

This replaces my older feature request #5534.

I propose the following new behavior of (({Range})):

  (1..3).to_a               # => [1, 2, 3]
  (3..1).to_a               # => [3, 2, 1]
  'a'..'c'.to_a             # => ['a', 'b', 'c']
  'c'..'a'.to_a             # => ['c', 'b', 'a']
  1...1 == 3...3            # => true
  1...1 == 'a'...'a'        # => true
  1...1 == Range::EMPTY_SET # => true
  1..2 == 1...3             # => false
  1...3.include?(2.5)       # => true

Also, maybe in the future the following behavior can be possible:

  r1 = Range.new('a', 'bc', :deglex)
  r1.include?('abc') # => false
  r1.to_a            # => ['a', 'b', ..., 'az', 'ba', 'bb', 'bc']
  r2 = Range.new('a', 'bc', :lex)
  r2.include?('abc') # => true
  r2.to_a            # => Error

and this:

  ((0.5)..(5.5)).to_a(Integer) # => [1, 2, 3, 4, 5]
  ((0.5)..(5.5)).each(Integer) do |i| puts i end

(i imagine this would require additions to the (({Integer})) class, so that it
know more about "real" ranges).


=end



-- 
http://bugs.ruby-lang.org/