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, wh=
ich 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 i=
n 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 =3D "abcdefgh"
r =3D nil

Benchmark.ips do |x|
  x.report("s[0, 3]") do
    r =3D S[0, 3]
  end
  x.report("s[0...3]") do
    r =3D 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 (=B1 2.3%) i/s -     46.495M in   5.003131s
            s[0...3]      8.471M (=B1 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 (=B131.9%) i/s -    114.054M in   5.016116s
            s[0...3]     26.553M (=B129.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 er=
ror
```

----------------------------------------
Feature #15950: Allow negative length in `Array#[]`, `Array#[]=3D`, `String=
#[]`, `String#[]=3D`
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] # =3D> "abc"
```

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

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

This is cumbersome.

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

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

If there is not enough characters or elements, it should stop at the bounda=
ry.

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





-- =

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

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