I believe I've tracked it down.

See this:
https://www.omniref.com/ruby/2.1.2/symbols/Array/%5B%5D#line=1261

which calls rb_ary_subseq
  http://rxr.whitequark.org/mri/source/array.c#1126

1. In the case where you passed in 5, it's larger than the length of the
array, so you get nil.

2. In the case where you passed in 4, it's the same as the length of the
array.  You passed in zero (0) as the 2nd param, which maps to "len" in the
C code.

It goes to this line: http://rxr.whitequark.org/mri/source/array.c#1137

   if (len <http://rxr.whitequark.org/mri/ident?i=len> == 0) return
ary_new <http://rxr.whitequark.org/mri/ident?i=ary_new>(klass
<http://rxr.whitequark.org/mri/ident?i=klass>, 0);


Then it goes here: http://rxr.whitequark.org/mri/source/array.c#399
    ary_new <http://rxr.whitequark.org/mri/ident?i=ary_new>(VALUE
<http://rxr.whitequark.org/mri/ident?i=VALUE> klass
<http://rxr.whitequark.org/mri/ident?i=klass>, long capa
<http://rxr.whitequark.org/mri/ident?i=capa> )

And then this line: http://rxr.whitequark.org/mri/source/array.c#423
ary <http://rxr.whitequark.org/mri/ident?i=ary> = ary_alloc
<http://rxr.whitequark.org/mri/ident?i=ary_alloc>(klass
<http://rxr.whitequark.org/mri/ident?i=klass>);

which is why you get an array of zero elements.





On Thu, Nov 13, 2014 at 1:42 PM, Rob Biedenharn <rob.biedenharn / gmail.com>
wrote:

>
> On 2014-Nov-13, at 12:39 , George Drummond <drummond / rentify.com> wrote:
>
> It is kind of strange.
>
> If you look at the examples section there is a "special cases" list and
> your example appears there.
>
> I don't know the reasons for this.
>
>
> Here's how *I* think about it:
>
>     [ :a, :b, :c, ]
>  ^   ^   ^   ^   ^   ^
>      0   1   2   3   4
>  -4  -3  -2  -1
>
> If the index "points" to positions "between" the actual elements, then you
> can treat the index 3 (in this case) as still being "inside" the Array
> brackets, but 4 is outside. If a slice starts "inside" the Array, it
> returns an Array, but if you completely "miss" the Array, you get nil.
>
> example = [ :a, :b, :c, ]
> (-4..4).each do |i|
>   puts "example[#{i}]  \t\#=> #{example[i].inspect}"
>   puts "example[#{i},2]\t\#=> #{example[i,2].inspect}"
> end
>
> example[-4]   #=> nil
> example[-4,2] #=> nil
> example[-3]   #=> :a
> example[-3,2] #=> [:a, :b]
> example[-2]   #=> :b
> example[-2,2] #=> [:b, :c]
> example[-1]   #=> :c
> example[-1,2] #=> [:c]
> example[0]   #=> :a
> example[0,2] #=> [:a, :b]
> example[1]   #=> :b
> example[1,2] #=> [:b, :c]
> example[2]   #=> :c
> example[2,2] #=> [:c]
> example[3]   #=> nil
> example[3,2] #=> []
> example[4]   #=> nil
> example[4,2] #=> nil
>
> Note that [2,2] can't actually give 2 elements because the Array is
> exhausted, but it returns what it can. [3,2] is similar: it runs out of
> elements before it find even one, but it starts "inside" so it gives an
> Array in return.
>
> -Rob
>
>
> On Thu, Nov 13, 2014 at 5:32 PM, leam hall <leamhall / gmail.com> wrote:
>
>>
>> On Thu, Nov 13, 2014 at 12:18 PM, George Drummond <drummond / rentify.com>
>> wrote:
>>
>>> Specifically the last line of documentation for this method: "Returns
>>> nil if the index (or starting index) are out of range."
>>>
>>
>> The nil part makes sense. What I don't get is why the first out of range,
>> "4", didn't also get nil.  The indices should be 0..3, right?
>>
>> --
>> Mind on a Mission <http://leamhall.blogspot.com/>
>>
>
>
>
> --
> George Drummond
> Software Engineer
>
> +44 (0)333 240 2222
>
>
> [image: Rentify]
>  6-8 Long Lane, London EC1A 9HF
>  www.rentify.com
>
>
>