Skip to content

Commit fb1aad3

Browse files
committed
Array#first and Array#last in Ruby
1 parent 4e65798 commit fb1aad3

File tree

2 files changed

+56
-17
lines changed

2 files changed

+56
-17
lines changed

array.c

Lines changed: 30 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1428,20 +1428,11 @@ enum ary_take_pos_flags
14281428
};
14291429

14301430
static VALUE
1431-
ary_take_first_or_last(int argc, const VALUE *argv, VALUE ary, enum ary_take_pos_flags last)
1431+
ary_take_first_or_last_n(VALUE ary, long n, enum ary_take_pos_flags last)
14321432
{
1433-
long n;
1434-
long len;
1433+
long len = RARRAY_LEN(ary);
14351434
long offset = 0;
14361435

1437-
argc = rb_check_arity(argc, 0, 1);
1438-
/* the case optional argument is omitted should be handled in
1439-
* callers of this function. if another arity case is added,
1440-
* this arity check needs to rewrite. */
1441-
RUBY_ASSERT_ALWAYS(argc == 1);
1442-
1443-
n = NUM2LONG(argv[0]);
1444-
len = RARRAY_LEN(ary);
14451436
if (n > len) {
14461437
n = len;
14471438
}
@@ -1454,6 +1445,17 @@ ary_take_first_or_last(int argc, const VALUE *argv, VALUE ary, enum ary_take_pos
14541445
return ary_make_partial(ary, rb_cArray, offset, n);
14551446
}
14561447

1448+
static VALUE
1449+
ary_take_first_or_last(int argc, const VALUE *argv, VALUE ary, enum ary_take_pos_flags last)
1450+
{
1451+
argc = rb_check_arity(argc, 0, 1);
1452+
/* the case optional argument is omitted should be handled in
1453+
* callers of this function. if another arity case is added,
1454+
* this arity check needs to rewrite. */
1455+
RUBY_ASSERT_ALWAYS(argc == 1);
1456+
return ary_take_first_or_last_n(ary, NUM2LONG(argv[0]), last);
1457+
}
1458+
14571459
/*
14581460
* call-seq:
14591461
* array << object -> self
@@ -2027,6 +2029,7 @@ rb_ary_at(VALUE ary, VALUE pos)
20272029
return rb_ary_entry(ary, NUM2LONG(pos));
20282030
}
20292031

2032+
#if 0
20302033
/*
20312034
* call-seq:
20322035
* array.first -> object or nil
@@ -2071,6 +2074,20 @@ rb_ary_first(int argc, VALUE *argv, VALUE ary)
20712074
return ary_take_first_or_last(argc, argv, ary, ARY_TAKE_FIRST);
20722075
}
20732076
}
2077+
#endif
2078+
2079+
static VALUE
2080+
ary_first(VALUE self)
2081+
{
2082+
return (RARRAY_LEN(self) == 0) ? Qnil : RARRAY_AREF(self, 0);
2083+
}
2084+
2085+
static VALUE
2086+
ary_last(VALUE self)
2087+
{
2088+
long len = RARRAY_LEN(self);
2089+
return (len == 0) ? Qnil : RARRAY_AREF(self, len-1);
2090+
}
20742091

20752092
/*
20762093
* call-seq:
@@ -2107,12 +2124,10 @@ rb_ary_first(int argc, VALUE *argv, VALUE ary)
21072124
*/
21082125

21092126
VALUE
2110-
rb_ary_last(int argc, const VALUE *argv, VALUE ary)
2127+
rb_ary_last(int argc, const VALUE *argv, VALUE ary) // used by parse.y
21112128
{
21122129
if (argc == 0) {
2113-
long len = RARRAY_LEN(ary);
2114-
if (len == 0) return Qnil;
2115-
return RARRAY_AREF(ary, len-1);
2130+
return ary_last(ary);
21162131
}
21172132
else {
21182133
return ary_take_first_or_last(argc, argv, ary, ARY_TAKE_LAST);
@@ -8809,8 +8824,6 @@ Init_Array(void)
88098824
rb_define_method(rb_cArray, "[]=", rb_ary_aset, -1);
88108825
rb_define_method(rb_cArray, "at", rb_ary_at, 1);
88118826
rb_define_method(rb_cArray, "fetch", rb_ary_fetch, -1);
8812-
rb_define_method(rb_cArray, "first", rb_ary_first, -1);
8813-
rb_define_method(rb_cArray, "last", rb_ary_last, -1);
88148827
rb_define_method(rb_cArray, "concat", rb_ary_concat_multi, -1);
88158828
rb_define_method(rb_cArray, "union", rb_ary_union_multi, -1);
88168829
rb_define_method(rb_cArray, "difference", rb_ary_difference_multi, -1);

array.rb

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,4 +66,30 @@ def sample(n = (ary = false), random: Random)
6666
Primitive.ary_sample(random, n, ary)
6767
end
6868
end
69+
70+
def first n = unspecified = true
71+
if Primitive.mandatory_only?
72+
Primitive.attr! :leaf
73+
Primitive.cexpr! %q{ ary_first(self) }
74+
else
75+
if unspecified
76+
Primitive.cexpr! %q{ ary_first(self) }
77+
else
78+
Primitive.cexpr! %q{ ary_take_first_or_last_n(self, NUM2LONG(n), ARY_TAKE_FIRST) }
79+
end
80+
end
81+
end
82+
83+
def last n = unspecified = true
84+
if Primitive.mandatory_only?
85+
Primitive.attr! :leaf
86+
Primitive.cexpr! %q{ ary_last(self) }
87+
else
88+
if unspecified
89+
Primitive.cexpr! %q{ ary_last(self) }
90+
else
91+
Primitive.cexpr! %q{ ary_take_first_or_last_n(self, NUM2LONG(n), ARY_TAKE_LAST) }
92+
end
93+
end
94+
end
6995
end

0 commit comments

Comments
 (0)