[ruby-core:93317] [Ruby trunk Feature#15950] Allow negative length in `Array#[]`, `Array#[]=`, `String#[]`, `String#[]=`

From: eregontp@...
Date: 2019-06-22 14:29:46 UTC
List: ruby-core #93317
Issue #15950 has been updated by Eregon (Benoit Daloze).


sawa (Tsuyoshi Sawada) wrote:
> And needless to say, this proposal would be irrelevant to Ruby beginners who insist on needlessly creating a range object as in `"abcdefg"[0...3]`  to take the first three characters of the string, when you can, and should, do `"abcdefg"[0, 3]`, which is more straightforward and efficient.

I am not a Ruby beginner and I would still recommend the Range notation, which I think is more idiomatic and easier to read. So whether people should use the Range notation or not is obviously subjective.

Moreover, you mention performance but it's not so relevant here.
For instance, TruffleRuby can escape analyze the Range, so it has no cost in this case.
And even on MRI in such a micro-benchmark there is only 10% of difference, which seems negligible.

```ruby
require 'benchmark/ips'

S = "abcdefgh"
r = nil

Benchmark.ips do |x|
  x.report("s[0, 3]") do
    r = S[0, 3]
  end
  x.report("s[0...3]") do
    r = S[0...3]
  end
  x.compare!
end
```

Results:
```
ruby -v bench.rb
ruby 2.6.2p47 (2019-03-13 revision 67232) [x86_64-linux]
Warming up --------------------------------------
             s[0, 3]   411.458k i/100ms
            s[0...3]   369.962k i/100ms
Calculating -------------------------------------
             s[0, 3]      9.298M (2.3%) i/s -     46.495M in   5.003131s
            s[0...3]      8.471M (ア 1.8%) i/s -     42.546M in   5.024158s

Comparison:
             s[0, 3]:  9298307.0 i/s
            s[0...3]:  8470923.4 i/s - 1.10x  slower
```

```
ruby -v bench.rb
truffleruby 19.0.0, like ruby 2.6.2, GraalVM CE Native [x86_64-linux]
Warming up --------------------------------------
             s[0, 3]     1.201M i/100ms
            s[0...3]     1.204M i/100ms
Calculating -------------------------------------
             s[0, 3]     27.141M (ア31.9%) i/s -    114.054M in   5.016116s
            s[0...3]     26.553M (ア29.1%) i/s -    115.561M in   5.044515s

Comparison:
             s[0, 3]: 27140752.2 i/s
            s[0...3]: 26553278.2 i/s - same-ish: difference falls within error
```

----------------------------------------
Feature #15950: Allow negative length in `Array#[]`, `Array#[]=`, `String#[]`, `String#[]=`
https://bugs.ruby-lang.org/issues/15950#change-78792

* Author: sawa (Tsuyoshi Sawada)
* Status: Rejected
* Priority: Normal
* Assignee: 
* Target version: 
----------------------------------------
To take the first n characters of a string, using `[]` is straightforward:

```ruby
"abcdefgh"[0, 3] # => "abc"
```

But to take the last n characters, we need to use n in two arguments: in the index (in negative form) in addition to the length:

```ruby
"abcdefgh"[-3, 3] # => "fgh"
```

This is cumbersome.

I wish negative length to be allowed, and be interpreted as measuring leftward (while cycling the receiver if necessary).

```ruby
"abcdefgh"[0, -3] # => "fgh"
"abcdefgh"[5, -3] # => "cde"
```

If there is not enough characters or elements, it should stop at the boundary.

```ruby
"abcdefgh"[1, -3] # => "a"
```





-- 
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>

In This Thread

Prev Next