Issue #14799 has been updated by shyouhei (Shyouhei Urabe).


zverok (Victor Shepelev) wrote:
> > how should Range#each work for this kind of ranges?
> 
> Most probably it should not (the same as `Enumerable#reverse_each` or `last(5)` doesn't have a sense for already implemented endless ranges), just raise.

Sounds reasonable, except it seems endless range does not raise for #reverse_each :)

```
zsh % ruby -ve '(1..).reverse_each {|i| p i }'
ruby 2.6.0dev (2018-05-29 trunk 63514) [x86_64-darwin15]
^CTraceback (most recent call last):
        2: from -e:1:in `<main>'
        1: from -e:1:in `reverse_each'
-e:1:in `each': Interrupt

```

----------------------------------------
Feature #14799: Startless range
https://bugs.ruby-lang.org/issues/14799#change-72309

* Author: zverok (Victor Shepelev)
* Status: Open
* Priority: Normal
* Assignee: 
* Target version: 
----------------------------------------
On introduction of endless range at #12912, "startless range" was discussed this way:

> @sowieso: Not having the opposite (`..5` and `..-2`) feels like this is rather a hack than a thoroughly planned feature.

> @duerst: I don't understand the need for a `..5` Range. The feature is called "endless range". Although mathematically, it's possible to think about startless ranges, they don't work in a program. Maybe some programming languages have `..5` as a shortcut for `0..5`, but that's in any way a usual, bounded, range with a start and an end. It's conceptually totally different from `5..`, which is a range with a start but no end, an unbound range.

In the context of that ticket (ranges used mostly for slicing arrays) having `..5` was indeed hard to justify, but there are other cases when `..5` being `-Infinity..5` is absolutely reasonable:

```ruby
case release_date
when ..1.year.ago 
  puts "ancient"
when 1.year.ago..3.months.ago
  puts "old"
when 3.months.ago..Date.today
  puts "recent"
when Date.today..
  puts "upcoming"
end

log.map(&:logged_at).grep(..Date.new(1980)) # => outliers due to bad log parsing...
```

E.g., whenever case equality operator is acting, having startless range to express "below this value" is the most concise and readable way. Also, for expressing constants (mostly decorative, but very readable):

```ruby
# Celsius degrees
WORK_RANGES = {
   ..-10 => :turn_off,
  -10..0 => :energy_saving,
  0..20 => :main,
  20..35 => :cooling,
  35.. => :turn_off
}
```

In addition, my related proposal #14784 suggests that this kind of ranges could be utilized by more powerful clamp too:

```ruby
updated_at.clamp(..Date.today)
```

**Uncertainty points:**

* Would it be hard to add to parser? I am not sure, I am not very good at it :(
* Should `..` be a thing? I guess not, unless there would be convincing real-life examples, which for me it is hard to think of.



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

Unsubscribe: <mailto:ruby-core-request / ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>