Feature #4541
Inconsistent Array.slice()
| Status: | Assigned | Start date: | 03/31/2011 | |
|---|---|---|---|---|
| Priority: | Normal | Due date: | ||
| Assignee: | % Done: | 0% |
||
| Category: | core | |||
| Target version: | 2.0.0 |
Description
Array slice/[] method is a bit inconsistent. Is it just poorly documented "feature" or a bug? In API doc I can't find this behaviour mentioned as a "special case".
def test_array_slice array = ['a', 'b', 'c'] assert_equal nil, array[3] assert_eaual nil, array[4] assert_eaual [], array[3, 0] # assert_equal nil, array[4, 0] # [] expected (or both nils in array[3, 0] and array[4, 0]) assert_equal ['c'], array[2..2] assert_equal [], array[3..3] # assert_equal nil, array[4..4] # [] expected (or both nils in array[3..3] and array[4..4]) end
Same behaviour can be reproduced on ruby 1.8.7 (2010-12-23 patchlevel 330) [x86_64-linux].
Related issues
History
Updated by naruse (Yui NARUSE) about 1 year ago
- Status changed from Open to Assigned
- Assignee set to matz (Yukihiro Matsumoto)
The fix may be following but it can be a spec...
diff --git a/array.c b/array.c index bdeb768..4721387 100644
+++ b/array.c @@ -948,7 +948,7 @@ rb_ary_subseq(VALUE ary, long beg, long len)
{
VALUE klass;- if (beg > RARRAY_LEN(ary)) return Qnil;
if (beg >= RARRAY_LEN(ary)) return Qnil;
if (beg < 0 || len < 0) return Qnil;
if (RARRAY_LEN(ary) < len || RARRAY_LEN(ary) < beg + len) {
Updated by marcandre (Marc-Andre Lafortune) about 1 year ago
Hi,
On Tue, Apr 5, 2011 at 3:04 AM, Yui NARUSE <redmine@ruby-lang.org> wrote: > > Issue #4541 has been updated by Yui NARUSE. > > Status changed from Open to Assigned > Assignee set to Yukihiro Matsumoto > > The fix may be following but it can be a spec... > > diff --git a/array.c b/array.c > index bdeb768..4721387 100644 > --- a/array.c > +++ b/array.c > @@ -948,7 +948,7 @@ rb_ary_subseq(VALUE ary, long beg, long len) > { > VALUE klass; > > - if (beg > RARRAY_LEN(ary)) return Qnil; > + if (beg >= RARRAY_LEN(ary)) return Qnil; > if (beg < 0 || len < 0) return Qnil; > > if (RARRAY_LEN(ary) < len || RARRAY_LEN(ary) < beg + len) {
With all due respect, I am strongly opposed to that change. There is no way that the following results should change:
array[0...3] # => ["a", "b", "c"] array[1...3] # => ["b", "c"] array[2...3] # => ["c"] array[3...3] # => [], as it *must* be.
The only possible change would be that array[42..42] returns [] instead of nil. For consistency's sake, `String#slice` would also have to be changed. I am not in favor of that change either, for compatibility reason and because I feel the current API makes sense. See my comment on issue #4245 [ruby-core:34197]. This issue is a duplicate of #4245.
Updated by zimbatm (Jonas Pfenniger) about 1 year ago
I don't see the advantage of having nil returned in any case since the empty array already expresses the "there is no object in that range".
Out of bound can be tested separately if necessary, but most of the cases you just want to get a range and a resulting array. Having also nil being returned means that you need some more code to test return.nil? && return.empty?
Updated by nahi (Hiroshi Nakamura) 11 months ago
- Target version changed from 1.9.2 to 1.9.3
Updated by nobu (Nobuyoshi Nakada) 11 months ago
Updated by rosenfeld (Rodrigo Rosenfeld Rosas) 11 months ago
Updated by gwright (Gary Wright) 11 months ago
Updated by marcandre (Marc-Andre Lafortune) 11 months ago
- Tracker changed from Bug to Feature
Updated by marcandre (Marc-Andre Lafortune) 11 months ago
- Category set to core
- Target version changed from 1.9.3 to 2.0.0