Bugs item #6410, was opened at 2006-10-31 01:48
You can respond by visiting: 
http://rubyforge.org/tracker/?func=detail&atid=1698&aid=6410&group_id=426

Category: Language / Runtime / Core Libraries
Group: 1.9.x
>Status: Closed
>Resolution: Out of Date
Priority: 3
Submitted By: Murphy (Kornelius Kalnbach) (murphy)
Assigned to: Shyouhei Urabe (shyouhei)
>Summary: [TINY][PATCH] Array#last is not working for n > 3

Initial Comment:
With Ruby 1.9 HEAD I get this:

irb(main):001:0> a = Array(1..25)
=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25]
irb(main):002:0> a.last(10)
=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
irb(main):003:0> a.last(3)
=> [23, 24, 25]
irb(main):004:0> a.last(10)
=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
irb(main):005:0> a.last(1)
=> [25]
irb(main):006:0> a.last(3)
=> [23, 24, 25]
irb(main):007:0> a.last(4)
=> [1, 2, 3, 4]

The reason seems to be in array.c, ary_shared_first():

    if (ARY_EMBED_P(ary) || n <= RARRAY_EMBED_LEN_MAX) {
	return rb_ary_new4(n, RARRAY_PTR(ary)+offset);
    }
    else {
	result = ary_shared_array(rb_cArray, ary);
	RARRAY(result)->as.heap.len = n;
    }

ary_shared_first (which realizes rb_ary_last) totally ignores the offset value.

A simple solution is not to use a shared array for #last:

    if (last || ARY_EMBED_P(ary) || n <= RARRAY_EMBED_LEN_MAX) {

Works for me. maybe there is a better solution.

Sorry that I didn't make a patch, I'm still learning how to use CVS...

----------------------------------------------------------------------

>Comment By: Murphy (Kornelius Kalnbach) (murphy)
Date: 2007-05-30 01:03

Message:
Seems to be fixed now. I close the ticket.

----------------------------------------------------------------------

Comment By: Murphy (Kornelius Kalnbach) (murphy)
Date: 2006-10-31 01:50

Message:
The patch :)

----------------------------------------------------------------------

You can respond by visiting: 
http://rubyforge.org/tracker/?func=detail&atid=1698&aid=6410&group_id=426