Project

General

Profile

Feature #12080 ยป v2-0001-Enumerable-Array-Range-first-Array-Range-last-wit.patch

rhenium (Kazuki Yamaguchi), 04/12/2016 01:40 PM

View differences:

array.c
1310 1310

  
1311 1311
/*
1312 1312
 *  call-seq:
1313
 *     ary.first     ->   obj or nil
1314
 *     ary.first(n)  ->   new_ary
1313
 *     ary.first                    ->  obj or nil
1314
 *     ary.first    { |obj| block } ->  obj or nil
1315
 *     ary.first(n)                 ->  new_ary
1316
 *     ary.first(n) { |obj| block } ->  new_ary
1315 1317
 *
1316 1318
 *  Returns the first element, or the first +n+ elements, of the array.
1317
 *  If the array is empty, the first form returns +nil+, and the
1318
 *  second form returns an empty array. See also Array#last for
1319
 *  the opposite effect.
1319
 *  If the array is empty, the first form returns +nil+, and the second form
1320
 *  returns an empty array.
1321
 *  If a block is given, only elements for which the given block returns a true
1322
 *  value are counted.
1323
 *
1324
 *  See also Array#last for the opposite effect.
1320 1325
 *
1321
 *     a = [ "q", "r", "s", "t" ]
1322
 *     a.first     #=> "q"
1323
 *     a.first(2)  #=> ["q", "r"]
1326
 *     a = [ "q", "r", "s", "t", "aa" ]
1327
 *     a.first                    #=> "q"
1328
 *     a.first(2)                 #=> ["q", "r"]
1329
 *     a.first { |i| i.size > 1 } #=> "aa"
1324 1330
 */
1325 1331

  
1326 1332
static VALUE
1327 1333
rb_ary_first(int argc, VALUE *argv, VALUE ary)
1328 1334
{
1329
    if (argc == 0) {
1330
	if (RARRAY_LEN(ary) == 0) return Qnil;
1331
	return RARRAY_AREF(ary, 0);
1335
    if (!rb_block_given_p()) {
1336
	if (argc == 0) {
1337
	    if (RARRAY_LEN(ary) == 0) return Qnil;
1338
	    return RARRAY_AREF(ary, 0);
1339
	}
1340
	else {
1341
	    return ary_take_first_or_last(argc, argv, ary, ARY_TAKE_FIRST);
1342
	}
1332 1343
    }
1333 1344
    else {
1334
	return ary_take_first_or_last(argc, argv, ary, ARY_TAKE_FIRST);
1345
	long i;
1346
	if (argc == 0) {
1347
	    for (i = 0; i < RARRAY_LEN(ary); i++) {
1348
		if (RTEST(rb_yield(RARRAY_AREF(ary, i))))
1349
		    return RARRAY_AREF(ary, i);
1350
	    }
1351
	    return Qnil;
1352
	}
1353
	else {
1354
	    long take = NUM2LONG(argv[0]);
1355
	    VALUE result = rb_ary_new();;
1356
	    if (take < 0) rb_raise(rb_eArgError, "attempt to take negative size");
1357
	    if (take == 0) return rb_ary_new2(0);
1358
	    for (i = 0; i < RARRAY_LEN(ary); i++) {
1359
		if (RTEST(rb_yield(RARRAY_AREF(ary, i)))) {
1360
		    rb_ary_push(result, RARRAY_AREF(ary, i));
1361
		    if (!--take) break;
1362
		}
1363
	    }
1364
	    return result;
1365
	}
1335 1366
    }
1336 1367
}
1337 1368

  
1338 1369
/*
1339 1370
 *  call-seq:
1340
 *     ary.last     ->  obj or nil
1341
 *     ary.last(n)  ->  new_ary
1371
 *     ary.last                    ->  obj or nil
1372
 *     ary.last    { |obj| block } ->  obj or nil
1373
 *     ary.last(n)                 ->  new_ary
1374
 *     ary.last(n) { |obj| block } ->  new_ary
1342 1375
 *
1343
 *  Returns the last element(s) of +self+. If the array is empty,
1344
 *  the first form returns +nil+.
1376
 *  Returns the last element(s) of +self+. If the array is empty, the first
1377
 *  form returns +nil+.
1378
 *  If a block is given, only elements for which the given block returns a true
1379
 *  value are counted.
1345 1380
 *
1346 1381
 *  See also Array#first for the opposite effect.
1347 1382
 *
1348
 *     a = [ "w", "x", "y", "z" ]
1349
 *     a.last     #=> "z"
1350
 *     a.last(2)  #=> ["y", "z"]
1383
 *     a = [ "w", "x", "y", "z", "aa" ]
1384
 *     a.last                     #=> "aa"
1385
 *     a.last(2)                  #=> ["z", "aa"]
1386
 *     a.last { |i| i.size == 1 } #=> "x"
1351 1387
 */
1352 1388

  
1353 1389
VALUE
1354 1390
rb_ary_last(int argc, const VALUE *argv, VALUE ary)
1355 1391
{
1356
    if (argc == 0) {
1357
	long len = RARRAY_LEN(ary);
1358
	if (len == 0) return Qnil;
1359
	return RARRAY_AREF(ary, len-1);
1392
    if (!rb_block_given_p()) {
1393
	if (argc == 0) {
1394
	    long len = RARRAY_LEN(ary);
1395
	    if (len == 0) return Qnil;
1396
	    return RARRAY_AREF(ary, len-1);
1397
	}
1398
	else {
1399
	    return ary_take_first_or_last(argc, argv, ary, ARY_TAKE_LAST);
1400
	}
1360 1401
    }
1361 1402
    else {
1362
	return ary_take_first_or_last(argc, argv, ary, ARY_TAKE_LAST);
1403
	long i;
1404
	if (argc == 0) {
1405
	    for (i = RARRAY_LEN(ary); --i >= 0; ) {
1406
		if (RTEST(rb_yield(RARRAY_AREF(ary, i))))
1407
		    return RARRAY_AREF(ary, i);
1408
	    }
1409
	    return Qnil;
1410
	}
1411
	else {
1412
	    long take = NUM2LONG(argv[0]);
1413
	    VALUE result = rb_ary_new();;
1414
	    if (take < 0) rb_raise(rb_eArgError, "attempt to take negative size");
1415
	    if (take == 0) return rb_ary_new2(0);
1416
	    for (i = RARRAY_LEN(ary); --i >= 0; ) {
1417
		if (RTEST(rb_yield(RARRAY_AREF(ary, i)))) {
1418
		    rb_ary_push(result, RARRAY_AREF(ary, i));
1419
		    if (!--take) break;
1420
		}
1421
	    }
1422
	    return rb_ary_reverse(result);
1423
	}
1363 1424
    }
1364 1425
}
1365 1426

  
enum.c
909 909
    UNREACHABLE;
910 910
}
911 911

  
912
static VALUE
913
take_find_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, params))
914
{
915
    struct MEMO *memo = MEMO_CAST(params);
916
    ENUM_WANT_SVALUE();
917
    if (RTEST(rb_yield(i))) {
918
	rb_ary_push(memo->v1, i);
919
	if (!--memo->u3.cnt) rb_iter_break();
920
    }
921
    return Qnil;
922
}
923

  
912 924
static VALUE enum_take(VALUE obj, VALUE n);
913 925

  
914 926
/*
915 927
 *  call-seq:
916
 *     enum.first       ->  obj or nil
917
 *     enum.first(n)    ->  an_array
928
 *     enum.first                    ->  obj or nil
929
 *     enum.first    { |obj| block } ->  obj or nil
930
 *     enum.first(n)                 ->  an_array
931
 *     enum.first(n) { |obj| block } ->  an_array
918 932
 *
919 933
 *  Returns the first element, or the first +n+ elements, of the enumerable.
920 934
 *  If the enumerable is empty, the first form returns <code>nil</code>, and the
921 935
 *  second form returns an empty array.
936
 *  If a block is given, only elements for which the given block returns a true
937
 *  value are counted.
922 938
 *
923
 *    %w[foo bar baz].first     #=> "foo"
924
 *    %w[foo bar baz].first(2)  #=> ["foo", "bar"]
925
 *    %w[foo bar baz].first(10) #=> ["foo", "bar", "baz"]
926
 *    [].first                  #=> nil
927
 *    [].first(10)              #=> []
939
 *    %w[foo bar baz].first            #=> "foo"
940
 *    %w[foo bar baz].first(2)         #=> ["foo", "bar"]
941
 *    %w[foo bar baz].first(10)        #=> ["foo", "bar", "baz"]
942
 *    [].first                         #=> nil
943
 *    [].first(10)                     #=> []
944
 *    [1,2,3,4].first { |i| i.even? }  #=> 2
945
 *    [1,2,2,2].first(2) { |i| i > 1 } #=> [2, 2]
928 946
 *
929 947
 */
930 948

  
......
932 950
enum_first(int argc, VALUE *argv, VALUE obj)
933 951
{
934 952
    struct MEMO *memo;
953
    long len;
935 954
    rb_check_arity(argc, 0, 1);
955

  
936 956
    if (argc > 0) {
937
	return enum_take(obj, argv[0]);
957
	if (!rb_block_given_p()) return enum_take(obj, argv[0]);
958

  
959
	len = NUM2LONG(argv[0]);
960
	if (len < 0) rb_raise(rb_eArgError, "attempt to take negative size");
961
	if (len == 0) return rb_ary_new2(0);
962

  
963
	memo = MEMO_NEW(rb_ary_new(), 0, len);
964
	rb_block_call(obj, id_each, 0, 0, take_find_i, (VALUE)memo);
965
	return memo->v1;
938 966
    }
939 967
    else {
940 968
	memo = MEMO_NEW(Qnil, 0, 0);
941
	rb_block_call(obj, id_each, 0, 0, first_i, (VALUE)memo);
969
	rb_block_call(obj, id_each, 0, 0, rb_block_given_p() ? find_i : first_i, (VALUE)memo);
942 970
	return memo->v1;
943 971
    }
944 972
}
945 973

  
946

  
947 974
/*
948 975
 *  call-seq:
949 976
 *     enum.sort                  -> array
gc.c
6094 6094
rb_gc_register_mark_object(VALUE obj)
6095 6095
{
6096 6096
    VALUE ary_ary = GET_THREAD()->vm->mark_object_ary;
6097
    VALUE ary = rb_ary_last(0, 0, ary_ary);
6097
    VALUE ary = Qnil;
6098
    if (RARRAY_LEN(ary_ary))
6099
	ary = RARRAY_AREF(ary_ary, RARRAY_LEN(ary_ary) - 1);
6098 6100

  
6099 6101
    if (ary == Qnil || RARRAY_LEN(ary) >= MARK_OBJECT_ARY_BUCKET_SIZE) {
6100 6102
	ary = rb_ary_tmp_new(MARK_OBJECT_ARY_BUCKET_SIZE);
range.c
851 851

  
852 852
/*
853 853
 *  call-seq:
854
 *     rng.first    -> obj
855
 *     rng.first(n) -> an_array
854
 *     rng.first                    -> obj
855
 *     rng.first   { |obj| block }  -> obj
856
 *     rng.first(n)                 -> an_array
857
 *     rng.first(n) { |obj| block } -> an_array
856 858
 *
857 859
 *  Returns the first object in the range, or an array of the first +n+
858 860
 *  elements.
861
 *  If a block is given, only elements for which the given block returns a true
862
 *  value are counted.
859 863
 *
860
 *    (10..20).first     #=> 10
861
 *    (10..20).first(3)  #=> [10, 11, 12]
864
 *    (10..20).first                   #=> 10
865
 *    (10..20).first { |i| i.odd? }    #=> 11
866
 *    (10..20).first(3)                #=> [10, 11, 12]
867
 *    (10..20).first(3) { |i| i.odd? } #=> [11, 13, 15]
862 868
 */
863 869

  
864 870
static VALUE
......
866 872
{
867 873
    VALUE n, ary[2];
868 874

  
875
    if (rb_block_given_p()) return rb_call_super(argc, argv);
869 876
    if (argc == 0) return RANGE_BEG(range);
870 877

  
871 878
    rb_scan_args(argc, argv, "1", &n);
......
879 886

  
880 887
/*
881 888
 *  call-seq:
882
 *     rng.last    -> obj
883
 *     rng.last(n) -> an_array
889
 *     rng.last                    -> obj
890
 *     rng.last   { |obj| block }  -> obj
891
 *     rng.last(n)                 -> an_array
892
 *     rng.last(n) { |obj| block } -> an_array
884 893
 *
885 894
 *  Returns the last object in the range,
886 895
 *  or an array of the last +n+ elements.
887
 *
888
 *  Note that with no arguments +last+ will return the object that defines
889
 *  the end of the range even if #exclude_end? is +true+.
890
 *
891
 *    (10..20).last      #=> 20
892
 *    (10...20).last     #=> 20
893
 *    (10..20).last(3)   #=> [18, 19, 20]
894
 *    (10...20).last(3)  #=> [17, 18, 19]
896
 *  If a block is given, only elements for which the given block returns a true
897
 *  value are counted.
898
 *
899
 *  Note that with no arguments nor a block +last+ will return the object that
900
 *  defines the end of the range even if #exclude_end? is +true+.
901
 *
902
 *    (10..20).last                    #=> 20
903
 *    (10...20).last                   #=> 20
904
 *    (10...20).last { true }          #=> 19
905
 *    (10..20).last(3)                 #=> [18, 19, 20]
906
 *    (10...20).last(3)                #=> [17, 18, 19]
907
 *    (10...20).last(3) { |i| i.odd? } #=> [15, 17, 19]
895 908
 */
896 909

  
897 910
static VALUE
898 911
range_last(int argc, VALUE *argv, VALUE range)
899 912
{
900
    if (argc == 0) return RANGE_END(range);
901
    return rb_ary_last(argc, argv, rb_Array(range));
913
    if (argc > 0 || rb_block_given_p()) {
914
	return rb_ary_last(argc, argv, rb_Array(range));
915
    }
916
    else {
917
	return RANGE_END(range);
918
    }
902 919
}
903 920

  
904 921

  
test/ruby/test_array.rb
756 756
  def test_first
757 757
    assert_equal(3,   @cls[3, 4, 5].first)
758 758
    assert_equal(nil, @cls[].first)
759
    assert_equal(2,   @cls[1, 2, 3, 4].first { |i| i.even? })
760
    assert_equal(nil, @cls[1, 2, 3, 4].first { |i| i > 100 })
759 761
  end
760 762

  
761 763
  def test_flatten
......
1059 1061
    assert_equal(nil, @cls[].last)
1060 1062
    assert_equal(1, @cls[1].last)
1061 1063
    assert_equal(99, @cls[*(3..99).to_a].last)
1064
    assert_equal(3, @cls[1, 2, 3, 4].last { |i| i.odd? })
1065
    assert_equal(nil, @cls[1, 2, 3, 4].last { |i| i > 100 })
1062 1066
  end
1063 1067

  
1064 1068
  def test_length
......
1999 2003
  def test_first2
2000 2004
    assert_equal([0], [0].first(2))
2001 2005
    assert_raise(ArgumentError) { [0].first(-1) }
2006
    assert_equal([2, 4], @cls[1, 2, 4, 6].first(2) { |i| i.even? })
2007
    assert_equal([2, 4, 6], @cls[2, 4, 5, 6].first(10) { |i| i.even? })
2008
    assert_raise(ArgumentError) { @cls[1, 2].first(-1) { |i| i.even? } }
2002 2009
  end
2003 2010

  
2004 2011
  def test_last2
2005 2012
    assert_equal([0], [0].last(2))
2006 2013
    assert_raise(ArgumentError) { [0].last(-1) }
2014
    assert_equal([4, 6], @cls[2, 4, 5, 6].last(2) { |i| i.even? })
2015
    assert_equal([2, 4, 6], @cls[2, 4, 5, 6].last(10) { |i| i.even? })
2016
    assert_raise(ArgumentError) { @cls[1, 2].last(-1) { |i| i.even? } }
2007 2017
  end
2008 2018

  
2009 2019
  def test_shift2
test/ruby/test_enum.rb
267 267
    assert_equal([1, 2, 3], @obj.first(3))
268 268
    assert_nil(@empty.first)
269 269
    assert_equal([], @empty.first(10))
270
    assert_equal(2, @obj.first { |i| i.even? })
271
    assert_equal([3], @obj.first(2) { |i| i > 2 })
270 272

  
271 273
    bug5801 = '[ruby-dev:45041]'
272 274
    assert_in_out_err([], <<-'end;', [], /unexpected break/, bug5801)
test/ruby/test_range.rb
271 271
    assert_equal("a", ("a".."c").first)
272 272
    assert_equal("c", ("a".."c").last)
273 273
    assert_equal(0, (2..0).last)
274
    assert_equal(1, (0..11).first { |i| i.odd? })
275
    assert_equal(11, (0..11).last { |i| i.odd? })
276
    assert_equal([1, 3], (0..11).first(2) { |i| i.odd? })
277
    assert_equal([9, 11], (0..11).last(2) { |i| i.odd? })
274 278

  
275 279
    assert_equal([0, 1, 2], (0...10).first(3))
276 280
    assert_equal([7, 8, 9], (0...10).last(3))
......
279 283
    assert_equal("a", ("a"..."c").first)
280 284
    assert_equal("c", ("a"..."c").last)
281 285
    assert_equal(0, (2...0).last)
286
    assert_equal(1, (0...11).first { |i| i.odd? })
287
    assert_equal(9, (0...11).last { |i| i.odd? })
288
    assert_equal([1, 3], (0...11).first(2) { |i| i.odd? })
289
    assert_equal([7, 9], (0...11).last(2) { |i| i.odd? })
282 290
  end
283 291

  
284 292
  def test_to_s
285
-