遠藤と申します。

先頭の要素以外の配列を返す Array#tail というメソッドを提案します。

  [1, 2, 3, 4].tail #=> [2, 3, 4]


現状では ary[1..-1] がイディオムになっていると思いますが、

  - インデックスに負の値を使っていてややトリッキー
  - (私の主観では) 見栄えもあまり良くない
  - そのわりにかなり頻出

なので、専用のメソッドで ary.tail と書けるといいと思います。

# 「Haskell 脳にやさしい」という効果もあります (?)


String#[] なども含むので正確な値ではないですが、ruby のコード中だけでも
193 箇所ほどあります。

$ find . -name \*.rb | xargs grep "\[1\.\.-1\]" | wc -l
193


とりあえず実装してみました。
ついでに Array#head を first の alias にしています。

よろしくご検討下さい。


Index: array.c
===================================================================
--- array.c	(revision 13858)
+++ array.c	(working copy)
@@ -785,6 +785,8 @@
  *  call-seq:
  *     array.first     ->   obj or nil
  *     array.first(n)  ->   an_array
+ *     array.head      ->   obj or nil
+ *     array.head(n)   ->   an_array
  *
  *  Returns the first element, or the first +n+ elements, of the array.
  *  If the array is empty, the first form returns <code>nil</code>, and the
@@ -832,6 +834,48 @@
     }
 }

+/*  call-seq:
+ *     array.tail    -> obj or nil
+ *     array.tail(n) -> sub_array
+ *
+ *  Returns the array without the first element, or the first +n+ elements,
+ *  of <i>self</i>. If the array is empty, the first form returns
+ *  <code>nil</code>, and the second form returns an empty array.
+ *  Equivalent to:
+ *
+ *     def tail(n = 1)
+ *       raise ArgumentError, "negative array size" if n < 0
+ *       self[n..-1] || (n == 1 ? nil : [])
+ *     end
+ *
+ *     a = [ "q", "r", "s", "t" ]
+ *     a.tail     #=> ["r", "s", "t"]
+ *     a.tail(2)  #=> ["s", "t"]
+ *     a.tail(5)  #=> []
+ *     [].tail    #=> nil
+ *     [].tail(2) #=> []
+ */
+static VALUE
+rb_ary_tail(int argc, VALUE *argv, VALUE ary)
+{
+    VALUE len;
+    if (argc == 0) {
+	if (RARRAY_LEN(ary) == 0) return Qnil;
+	len = LONG2NUM(RARRAY_LEN(ary) - 1);
+	return ary_shared_first(1, &len, ary, Qtrue);
+    }
+    else if (NUM2LONG(argv[0]) < 0) {
+	rb_raise(rb_eArgError, "negative array size");
+    }
+    else if (RARRAY_LEN(ary) < NUM2LONG(argv[0])) {
+	return rb_ary_new3(0);
+    }
+    else {
+	argv[0] = LONG2NUM(RARRAY_LEN(ary) - NUM2LONG(argv[0]));
+	return ary_shared_first(argc, argv, ary, Qtrue);
+    }
+}
+
 /*
  *  call-seq:
  *     array.fetch(index)                    -> obj
@@ -3247,7 +3291,9 @@
     rb_define_method(rb_cArray, "at", rb_ary_at, 1);
     rb_define_method(rb_cArray, "fetch", rb_ary_fetch, -1);
     rb_define_method(rb_cArray, "first", rb_ary_first, -1);
+    rb_define_alias(rb_cArray,  "head", "first");
     rb_define_method(rb_cArray, "last", rb_ary_last, -1);
+    rb_define_method(rb_cArray, "tail", rb_ary_tail, -1);
     rb_define_method(rb_cArray, "concat", rb_ary_concat, 1);
     rb_define_method(rb_cArray, "<<", rb_ary_push, 1);
     rb_define_method(rb_cArray, "push", rb_ary_push_m, -1);
Index: test/ruby/test_array.rb
===================================================================
--- test/ruby/test_array.rb	(revision 13858)
+++ test/ruby/test_array.rb	(working copy)
@@ -720,6 +720,18 @@
     assert(a1.hash != a3.hash)
   end

+  def test_head
+    assert_equal(3,         @cls[3, 4, 5].head)
+    assert_equal([],        @cls[3, 4, 5].head(0))
+    assert_equal([3],       @cls[3, 4, 5].head(1))
+    assert_equal([3, 4],    @cls[3, 4, 5].head(2))
+    assert_equal([3, 4, 5], @cls[3, 4, 5].head(3))
+    assert_equal([3, 4, 5], @cls[3, 4, 5].head(4))
+    assert_raise(ArgumentError) { @cls[3, 4, 5].head(-1) }
+    assert_equal(nil,       @cls[].head)
+    assert_equal([],        @cls[].head(1))
+  end
+
   def test_include?
     a = @cls[ 'cat', 99, /a/, @cls[ 1, 2, 3] ]
     assert(a.include?('cat'))
@@ -1103,6 +1115,18 @@
     assert_equal(@cls[], @cls[].sort!)
   end

+  def test_tail
+    assert_equal([4, 5],    @cls[3, 4, 5].tail)
+    assert_equal([3, 4, 5], @cls[3, 4, 5].tail(0))
+    assert_equal([4, 5],    @cls[3, 4, 5].tail(1))
+    assert_equal([5],       @cls[3, 4, 5].tail(2))
+    assert_equal([],        @cls[3, 4, 5].tail(3))
+    assert_equal([],        @cls[3, 4, 5].tail(4))
+    assert_raise(ArgumentError) { @cls[3, 4, 5].tail(-1) }
+    assert_equal(nil,       @cls[].tail)
+    assert_equal([],        @cls[].tail(1))
+  end
+
   def test_to_a
     a = @cls[ 1, 2, 3 ]
     a_id = a.__id__

-- 
Yusuke ENDOH <mame / tsg.ne.jp>