# Inconsistency in Array#[]

Disclaimer: I know what docs say, but I’d prefer a different
behaviour. I want to understand why this design decision was made.

Some code first:
irb(main):001:0> a = [1,2,3,4,5]
=> [1, 2, 3, 4, 5]
irb(main):002:0> a[0,10]
=> [1, 2, 3, 4, 5] # ad 1
irb(main):003:0> a[-10,10]

1. Get 10 elements starting from the first element until the end of
the array. If array is smaller than 10 just return everything. This
makes sense, because in the range <0, 10) there are 5 elements that
can be returned.
2. Get 10 elements starting from the 10th element from the end, up to
the end. I got nil, but looking from -10 to 0 there are 5 elements, in
other words in the range (-10, 0> there are 5 elements, like in case

I expected I’d get the same result as in 1 (yes, no additional nils,
just the whole array). I think this isn’t really complying with the
principle of the least surprise. I’d be grateful if somebody can
explain me a reasoning behind this behaviour.

Greetings,
Wojciech P.

Hi –

On Mon, 3 Aug 2009, Wojciech P. wrote:

just the whole array). I think this isn’t really complying with the
principle of the least surprise. I’d be grateful if somebody can
explain me a reasoning behind this behaviour.

The way I see it, the process short-circuits as soon as it realizes
that you’re asking it to start at an out-of-range index. The same
happens here:

array = [1,2,3]
array[5,10] # => nil, because there’s no a[5]

I would also always expect that if this succeeds:

sub = array[x,y]

then this is true:

sub[0] == array[x]

since you’ve asked for a subarray starting at array[x]. If sub[0]
isn’t array[x], then the subarray cannot be said to have started at
array[x].

David

Hi,

Am Montag, 03. Aug 2009, 05:50:10 +0900 schrieb Wojciech P.:

I expected I’d get the same result as in 1 (yes, no additional nils,
just the whole array). I think this isn’t really complying with the
principle of the least surprise.

In the end, it is probably a matter of taste but I agree with you.
I would even prefer a behaviour like this:

a[3,-3] #=> [4,3,2]

This would be the least surprise to me.

I’m pleading for years for an `Array#notempty?' method analogous to`Numeric#nonzero?’ which would be a one-liner in C. But that
seems to be a real imposition on the developers community.

Bertram

VALUE rb_ary_notempty( ary)
VALUE ary;
{
return RARRAY( ary)->len == 0 ? Qnil : ary;
}

On Mon, Aug 3, 2009 at 5:17 PM, Bertram
Scharpf[email protected] wrote:

This would be the least surprise to me.
Stuttgart, Deutschland/Germany
http://www.bertram-scharpf.de

Really?

a = [1,2,3,4,5]
p a[3,2] #=> [4, 5]

#p a[3,-3] #=> [4,3,2]
#a[start,length]

This seems least surprising to me.

Harry

On Aug 3, 4:38 am, Harry K. [email protected] wrote:

Stuttgart, Deutschland/Germany
This seems least surprising to me.

Harry

A Look into Japanese Ruby List in Englishhttp://www.kakueki.com/ruby/list.html

I’m sorry to butt in, but your getting exactly what you ask for but
you expecting otherwise!

a[x, y] means starting at element x give me up to y elements

a = [1.2.3.4,5]
a[-3,3] => [3,4,5]
a[-3,4] => [3.4,5]

a[-3,0] => []

a[3,-3] => # there is no such thing -3 elements therefore it
returns nil

Hi,

Am Montag, 03. Aug 2009, 09:11:11 +0900 schrieb Bertram S.:

Am Montag, 03. Aug 2009, 05:50:10 +0900 schrieb Wojciech P.:

a = [1,2,3,4,5]

I would even prefer a behaviour like this:

a[3,-3] #=> [4,3,2]

This would be the least surprise to me.

Sorry! The least surprise of course would be

a[3,-3] #=> [3,2,1]

Bertram

Hi,

Am Dienstag, 04. Aug 2009, 08:40:06 +0900 schrieb bbiker:

returns nil
That’s the way it is. I wrote that my suggestion is a matter of
taste and it’s no more. The most weird thing would be to change
the language’s definition and the common sense.

Anyway, it is still my opinion that there should be methods
Array#notempty?, Hash.notempty? and String.notempty? analogous to
Numeric#nonzero?. Expect me to repeat it soon.

Bertram

Good evening,

On Mon, Aug 3, 2009 at 7:50 PM, Bertram S.
[email protected]wrote:

Hi,

Anyway, it is still my opinion that there should be methods
Array#notempty?, Hash.notempty? and String.notempty? analogous to
Numeric#nonzero?. Expect me to repeat it soon.

Have you actually written the patch to implement these methods and had
it
rejected? I can’t imagine at least not getting a very good reason from
the
core team why they wouldn’t put it in if you have a patch in hand for
them…

John

On Tue, Aug 4, 2009 at 8:40 AM, bbiker[email protected] wrote:

a[3,-3] #=> [4,3,2]
Bertram S.

a[x, y] means starting at element x give me up to y elements

I am not expecting otherwise.
I realize it does not work, and I understand why.
That is why it is commented out.

It was suggested that this type of behavior would be nice.

If it did work, I would expect it to work that way.

Harry

On Aug 3, 2009, at 11:11 PM, John W Higgins wrote:

Numeric#nonzero?. Expect me to repeat it soon.

Have you actually written the patch to implement these methods and
rejected? I can’t imagine at least not getting a very good reason
from the
core team why they wouldn’t put it in if you have a patch in hand for
them…

John

Just take a look at the definition of blank? (and present?) from the
ActiveSupport gem

activesupport-2.3.2/lib/active_support/core_ext/blank.rb

Yeah, it is bundled with Rails and this is the Ruby list, but it’s
only 58 lines (including comments and empty lines) of ruby code.

I typically add a NilClass#nonzero? just so nil plays nicely with
Numeric#nonzero? myself.

-Rob

Rob B. wrote:

Just take a look at the definition of blank? (and present?) from the
ActiveSupport gem

activesupport-2.3.2/lib/active_support/core_ext/blank.rb

I think that demonstrates a problem - there are different ideas of what
“notempty?” means. In the case of ActiveSupport, a string which consists
entirely of whitespace is “blank?”, even though it is not “empty?”

I typically add a NilClass#nonzero? just so nil plays nicely with
Numeric#nonzero? myself.

I find it useful how Javascript treats 0 and “” as false (although
strangely not an empty array). You can write things like

emit(doc.foo || null);

to make things consistent - null and empty string both map to null.

Maybe there’s a case for something that you can rely on being present at
the Object level:

class Object; def true?; true; end; end
class NilClass; def true?; false; end; end
class FalseClass; def true?; false; end; end
class String; def true?; !empty?; end; end
class Array; def true?; !empty?; end; end
class Numeric; def true?; !zero?; end; end

Then ‘true?’ could be called automatically in boolean contexts, like
‘if’ and ‘and’. The latter would be a big language change though.

I think the problem with this idea is the same as above: people would
disagree as to what’s the natural definition of ‘not empty’, as it would
vary from one application to another.

Hi,

Am Dienstag, 04. Aug 2009, 12:11:53 +0900 schrieb John W Higgins:

On Mon, Aug 3, 2009 at 7:50 PM, Bertram S. [email protected]wrote:

Anyway, it is still my opinion that there should be methods
Array#notempty?, Hash.notempty? and String.notempty? analogous to
Numeric#nonzero?. Expect me to repeat it soon.

Have you actually written the patch to implement these methods and had it
rejected?

Several. Here are two. (The links do not work any more.)

These are the sources in my private library:

Bertram

Hi,

Am Dienstag, 04. Aug 2009, 21:59:21 +0900 schrieb Brian C.:

Maybe there’s a case for something that you can rely on being present at
the Object level:

class Object; def true?; true; end; end
class NilClass; def true?; false; end; end
class FalseClass; def true?; false; end; end
class String; def true?; !empty?; end; end
class Array; def true?; !empty?; end; end
class Numeric; def true?; !zero?; end; end

Again: I use it for default values. Here’s an example.

class Array ; def notempty? ; self if any? ; end ; end

def halign list

end

halign lines.notempty? || %w{(no entries)}

Another name for any? doesn’t help here.

Bertram

Brian C. wrote:

I find it useful how Javascript treats 0 and “” as false (although
strangely not an empty array). You can write things like

but let’s not make ruby more like javascript

(search for “transitive”)