Project

General

Profile

Feature #12080 ยป 0001-Enumerable-Array-Range-first-Array-Range-last-with-b.patch

rhenium (Kazuki Yamaguchi), 02/17/2016 01:37 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 1319
 *  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.
1320
 *  second form returns an empty array.
1321
 *  If a block is given, only elements which the given block returns a true
1322
 *  value are counted.
1320 1323
 *
1321
 *     a = [ "q", "r", "s", "t" ]
1322
 *     a.first     #=> "q"
1323
 *     a.first(2)  #=> ["q", "r"]
1324
 *  See also Array#last for the opposite effect.
1325
 *
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 1376
 *  Returns the last element(s) of +self+. If the array is empty,
1344 1377
 *  the first form returns +nil+.
1345 1378
 *
1346 1379
 *  See also Array#first for the opposite effect.
1347 1380
 *
1348
 *     a = [ "w", "x", "y", "z" ]
1349
 *     a.last     #=> "z"
1350
 *     a.last(2)  #=> ["y", "z"]
1381
 *     a = [ "w", "x", "y", "z", "aa" ]
1382
 *     a.last                     #=> "aa"
1383
 *     a.last(2)                  #=> ["z", "aa"]
1384
 *     a.last { |i| i.size == 1 } #=> "x"
1351 1385
 */
1352 1386

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

  
enum.c
813 813
    UNREACHABLE;
814 814
}
815 815

  
816
static VALUE
817
take_find_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, params))
818
{
819
    struct MEMO *memo = MEMO_CAST(params);
820
    ENUM_WANT_SVALUE();
821
    if (RTEST(rb_yield(i))) {
822
	rb_ary_push(memo->v1, i);
823
	if (!--memo->u3.cnt) rb_iter_break();
824
    }
825
    return Qnil;
826
}
827

  
816 828
static VALUE enum_take(VALUE obj, VALUE n);
817 829

  
818 830
/*
819 831
 *  call-seq:
820
 *     enum.first       ->  obj or nil
821
 *     enum.first(n)    ->  an_array
832
 *     enum.first                    ->  obj or nil
833
 *     enum.first    { |obj| block } ->  obj or nil
834
 *     enum.first(n)                 ->  an_array
835
 *     enum.first(n) { |obj| block } ->  an_array
822 836
 *
823 837
 *  Returns the first element, or the first +n+ elements, of the enumerable.
824 838
 *  If the enumerable is empty, the first form returns <code>nil</code>, and the
825 839
 *  second form returns an empty array.
840
 *  If a block is given, only elements which the given block returns a true
841
 *  value are counted.
826 842
 *
827
 *    %w[foo bar baz].first     #=> "foo"
828
 *    %w[foo bar baz].first(2)  #=> ["foo", "bar"]
829
 *    %w[foo bar baz].first(10) #=> ["foo", "bar", "baz"]
830
 *    [].first                  #=> nil
831
 *    [].first(10)              #=> []
843
 *    %w[foo bar baz].first            #=> "foo"
844
 *    %w[foo bar baz].first(2)         #=> ["foo", "bar"]
845
 *    %w[foo bar baz].first(10)        #=> ["foo", "bar", "baz"]
846
 *    [].first                         #=> nil
847
 *    [].first(10)                     #=> []
848
 *    [1,2,3,4].first { |i| i.even? }  #=> 2
849
 *    [1,2,2,2].first(2) { |i| i > 1 } #=> [2, 2]
832 850
 *
833 851
 */
834 852

  
......
836 854
enum_first(int argc, VALUE *argv, VALUE obj)
837 855
{
838 856
    struct MEMO *memo;
857
    long len;
839 858
    rb_check_arity(argc, 0, 1);
859

  
840 860
    if (argc > 0) {
841
	return enum_take(obj, argv[0]);
861
	if (!rb_block_given_p()) return enum_take(obj, argv[0]);
862

  
863
	len = NUM2LONG(argv[0]);
864
	if (len < 0) rb_raise(rb_eArgError, "attempt to take negative size");
865
	if (len == 0) return rb_ary_new2(0);
866

  
867
	memo = MEMO_NEW(rb_ary_new(), 0, len);
868
	rb_block_call(obj, id_each, 0, 0, take_find_i, (VALUE)memo);
869
	return memo->v1;
842 870
    }
843 871
    else {
844 872
	memo = MEMO_NEW(Qnil, 0, 0);
845
	rb_block_call(obj, id_each, 0, 0, first_i, (VALUE)memo);
873
	rb_block_call(obj, id_each, 0, 0, rb_block_given_p() ? find_i : first_i, (VALUE)memo);
846 874
	return memo->v1;
847 875
    }
848 876
}
849 877

  
850

  
851 878
/*
852 879
 *  call-seq:
853 880
 *     enum.sort                  -> array
gc.c
5983 5983
rb_gc_register_mark_object(VALUE obj)
5984 5984
{
5985 5985
    VALUE ary_ary = GET_THREAD()->vm->mark_object_ary;
5986
    VALUE ary = rb_ary_last(0, 0, ary_ary);
5986
    VALUE ary = Qnil;
5987
    if (RARRAY_LEN(ary_ary))
5988
	ary = RARRAY_AREF(ary_ary, RARRAY_LEN(ary_ary) - 1);
5987 5989

  
5988 5990
    if (ary == Qnil || RARRAY_LEN(ary) >= MARK_OBJECT_ARY_BUCKET_SIZE) {
5989 5991
	ary = rb_ary_tmp_new(MARK_OBJECT_ARY_BUCKET_SIZE);
range.c
866 866
{
867 867
    VALUE n, ary[2];
868 868

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

  
871 872
    rb_scan_args(argc, argv, "1", &n);
......
897 898
static VALUE
898 899
range_last(int argc, VALUE *argv, VALUE range)
899 900
{
900
    if (argc == 0) return RANGE_END(range);
901
    return rb_ary_last(argc, argv, rb_Array(range));
901
    if (argc > 0 || rb_block_given_p()) {
902
	return rb_ary_last(argc, argv, rb_Array(range));
903
    }
904
    else {
905
	return RANGE_END(range);
906
    }
902 907
}
903 908

  
904 909

  
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
......
1962 1966
  def test_first2
1963 1967
    assert_equal([0], [0].first(2))
1964 1968
    assert_raise(ArgumentError) { [0].first(-1) }
1969
    assert_equal([2, 4], @cls[1, 2, 4, 6].first(2) { |i| i.even? })
1970
    assert_equal([2, 4, 6], @cls[2, 4, 5, 6].first(10) { |i| i.even? })
1971
    assert_raise(ArgumentError) { @cls[1, 2].first(-1) { |i| i.even? } }
1965 1972
  end
1966 1973

  
1967 1974
  def test_last2
1968 1975
    assert_equal([0], [0].last(2))
1969 1976
    assert_raise(ArgumentError) { [0].last(-1) }
1977
    assert_equal([4, 6], @cls[2, 4, 5, 6].last(2) { |i| i.even? })
1978
    assert_equal([2, 4, 6], @cls[2, 4, 5, 6].last(10) { |i| i.even? })
1979
    assert_raise(ArgumentError) { @cls[1, 2].last(-1) { |i| i.even? } }
1970 1980
  end
1971 1981

  
1972 1982
  def test_shift2
test/ruby/test_enum.rb
204 204
    assert_equal([1, 2, 3], @obj.first(3))
205 205
    assert_nil(@empty.first)
206 206
    assert_equal([], @empty.first(10))
207
    assert_equal(2, @obj.first { |i| i.even? })
208
    assert_equal([3], @obj.first(2) { |i| i > 2 })
207 209

  
208 210
    bug5801 = '[ruby-dev:45041]'
209 211
    assert_in_out_err([], <<-'end;', [], /unexpected break/)
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
-