Issue #7545 has been updated by alexeymuranov (Alexey Muranov).


drbrain (Eric Hodel) wrote:
> =begin
> How would (({(3..1).to_a})) be implemented? The opposite uses #succ today.

I propose the range to store a lazy ordered set, which is normally an interval in some bigger ordered set.  I have not specified an implementation, but for example it can store the bounds, unless the set is empty, and some kind of identifiers for the ambient set and for the order used. Probably this will have little in common with the current implementation.

As 3 and 1 are integers and 3 > 1, i propose to interpret the literal `3..1` as an interval in the set of integers, with the lower bound 3, the upper bound 1, and the order reverse to the usual order (3 < 2 < 1), designated by a symbol `:rev` for example.  I would propose to delegate the responsibility of converting `3..1` to an array to the `Integer` class (allowing also the explicit syntax `(3..1).to_a(Integer)`).  The `Integer` class should know how to iterate over a range when the bounds and the order (direction) are given.

Actually, what did you mean by "opposite"?

> Why should (({1...1})) equal (({3...3}))? I don't understand at all. This would break existing code.

Because, for example, currently

(1...1).to_a     # => []
(3...3).to_a     # => []
('a'...'a').to_a # => []

More precisely, because they are the same as ordered sets: all three are the empty set.

I understand that this proposal changes the existing behavior and so can break existing code.
However, i do not imagine easily an example of code where someone relies on the fact that 1...1 is not the same as 3...3

> In (({1...3.include?(2.5)})) is the change to Ruby syntax also part of the proposal, or a typo? (Currently NoMethodError is raised due to low precedence of (({...}). Is there something wrong with Range#cover?

Yes, there was a typo, i meant `(1...3).include?(2.5)`, and it is not a change, it already works like this. It was just for an example, that this behavior should stay.

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.
 
> What is a deglex? What is a lex?

I meant here different orders on the set of words, for example :lex for lexicographic, :deglex for graded lexicographic http://en.wikipedia.org/wiki/Monomial_order#Graded_lexicographic_order (there it is called "grlex").


----------------------------------------
Feature #7545: Make Range act as a "lazy ordered set"
https://bugs.ruby-lang.org/issues/7545#change-34629

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/