From 29eb1b16028928139dcaa236beb6d351c85f434c Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Sun, 26 Jan 2020 18:27:40 +0900 Subject: [PATCH] Moved Array#shuffle and Array#shuffle! to rbinc --- array.c | 56 +++------------------------- array.rb | 36 ++++++++++++++++++ common.mk | 3 ++ inits.c | 1 + spec/ruby/core/array/shuffle_spec.rb | 11 ++++-- 5 files changed, 53 insertions(+), 54 deletions(-) create mode 100755 array.rb diff --git a/array.c b/array.c index 7925b26e07..42248dbafd 100644 --- a/array.c +++ b/array.c @@ -29,6 +29,7 @@ #include "ruby/st.h" #include "ruby/util.h" #include "transient_heap.h" +#include "builtin.h" #if !ARRAY_DEBUG # define NDEBUG @@ -5342,39 +5343,11 @@ static ID id_random; #define RAND_UPTO(max) (long)rb_random_ulong_limited((randgen), (max)-1) -/* - * call-seq: - * ary.shuffle! -> ary - * ary.shuffle!(random: rng) -> ary - * - * Shuffles elements in +self+ in place. - * - * a = [ 1, 2, 3 ] #=> [1, 2, 3] - * a.shuffle! #=> [2, 3, 1] - * a #=> [2, 3, 1] - * - * The optional +rng+ argument will be used as the random number generator. - * - * a.shuffle!(random: Random.new(1)) #=> [1, 3, 2] - */ - static VALUE -rb_ary_shuffle_bang(int argc, VALUE *argv, VALUE ary) +rb_ary_shuffle_bang(rb_execution_context_t *ec, VALUE ary, VALUE randgen) { - VALUE opts, randgen = rb_cRandom; long i, len; - if (OPTHASH_GIVEN_P(opts)) { - VALUE rnd; - ID keyword_ids[1]; - - keyword_ids[0] = id_random; - rb_get_kwargs(opts, keyword_ids, 0, 1, &rnd); - if (rnd != Qundef) { - randgen = rnd; - } - } - rb_check_arity(argc, 0, 0); rb_ary_modify(ary); i = len = RARRAY_LEN(ary); RARRAY_PTR_USE(ary, ptr, { @@ -5392,28 +5365,11 @@ rb_ary_shuffle_bang(int argc, VALUE *argv, VALUE ary) return ary; } - -/* - * call-seq: - * ary.shuffle -> new_ary - * ary.shuffle(random: rng) -> new_ary - * - * Returns a new array with elements of +self+ shuffled. - * - * a = [ 1, 2, 3 ] #=> [1, 2, 3] - * a.shuffle #=> [2, 3, 1] - * a #=> [1, 2, 3] - * - * The optional +rng+ argument will be used as the random number generator. - * - * a.shuffle(random: Random.new(1)) #=> [1, 3, 2] - */ - static VALUE -rb_ary_shuffle(int argc, VALUE *argv, VALUE ary) +rb_ary_shuffle(rb_execution_context_t *ec, VALUE ary, VALUE randgen) { ary = rb_ary_dup(ary); - rb_ary_shuffle_bang(argc, argv, ary); + rb_ary_shuffle_bang(ec, ary, randgen); return ary; } @@ -7047,8 +7003,6 @@ Init_Array(void) rb_define_method(rb_cArray, "flatten", rb_ary_flatten, -1); rb_define_method(rb_cArray, "flatten!", rb_ary_flatten_bang, -1); rb_define_method(rb_cArray, "count", rb_ary_count, -1); - rb_define_method(rb_cArray, "shuffle!", rb_ary_shuffle_bang, -1); - rb_define_method(rb_cArray, "shuffle", rb_ary_shuffle, -1); rb_define_method(rb_cArray, "sample", rb_ary_sample, -1); rb_define_method(rb_cArray, "cycle", rb_ary_cycle, -1); rb_define_method(rb_cArray, "permutation", rb_ary_permutation, -1); @@ -7074,3 +7028,5 @@ Init_Array(void) id_random = rb_intern("random"); } + +#include "array.rbinc" diff --git a/array.rb b/array.rb new file mode 100755 index 0000000000..ed5779290f --- /dev/null +++ b/array.rb @@ -0,0 +1,36 @@ +#!/usr/bin/ruby +class Array + # call-seq: + # ary.shuffle! -> ary + # ary.shuffle!(random: rng) -> ary + # + # Shuffles elements in +self+ in place. + # + # a = [ 1, 2, 3 ] #=> [1, 2, 3] + # a.shuffle! #=> [2, 3, 1] + # a #=> [2, 3, 1] + # + # The optional +rng+ argument will be used as the random number generator. + # + # a.shuffle!(random: Random.new(1)) #=> [1, 3, 2] + def shuffle!(random: Random) + __builtin_rb_ary_shuffle_bang(random) + end + + # call-seq: + # ary.shuffle -> new_ary + # ary.shuffle(random: rng) -> new_ary + # + # Returns a new array with elements of +self+ shuffled. + # + # a = [ 1, 2, 3 ] #=> [1, 2, 3] + # a.shuffle #=> [2, 3, 1] + # a #=> [1, 2, 3] + # + # The optional +rng+ argument will be used as the random number generator. + # + # a.shuffle(random: Random.new(1)) #=> [1, 3, 2] + def shuffle(random: Random) + __builtin_rb_ary_shuffle(random); + end +end diff --git a/common.mk b/common.mk index b685e8fa4c..f9bef01cf3 100644 --- a/common.mk +++ b/common.mk @@ -1001,6 +1001,7 @@ BUILTIN_RB_SRCS = \ $(srcdir)/pack.rb \ $(srcdir)/trace_point.rb \ $(srcdir)/warning.rb \ + $(srcdir)/array.rb \ $(srcdir)/prelude.rb \ $(srcdir)/gem_prelude.rb \ $(empty) @@ -1601,7 +1602,9 @@ array.$(OBJEXT): $(top_srcdir)/internal/stdbool.h array.$(OBJEXT): $(top_srcdir)/internal/vm.h array.$(OBJEXT): $(top_srcdir)/internal/warnings.h array.$(OBJEXT): {$(VPATH)}array.c +array.$(OBJEXT): {$(VPATH)}array.rbinc array.$(OBJEXT): {$(VPATH)}assert.h +array.$(OBJEXT): {$(VPATH)}builtin.h array.$(OBJEXT): {$(VPATH)}config.h array.$(OBJEXT): {$(VPATH)}debug_counter.h array.$(OBJEXT): {$(VPATH)}defines.h diff --git a/inits.c b/inits.c index 91c916deec..39cbe5f8ba 100644 --- a/inits.c +++ b/inits.c @@ -83,6 +83,7 @@ rb_call_inits(void) BUILTIN(trace_point); BUILTIN(pack); BUILTIN(warning); + BUILTIN(array); Init_builtin_prelude(); } #undef CALL diff --git a/spec/ruby/core/array/shuffle_spec.rb b/spec/ruby/core/array/shuffle_spec.rb index 7a2fed7d50..106ef05ce2 100644 --- a/spec/ruby/core/array/shuffle_spec.rb +++ b/spec/ruby/core/array/shuffle_spec.rb @@ -25,10 +25,13 @@ describe "Array#shuffle" do ArraySpecs::MyArray[1, 2, 3].shuffle.should be_an_instance_of(Array) end - it "attempts coercion via #to_hash" do - obj = mock('hash') - obj.should_receive(:to_hash).once.and_return({}) - [2, 3].shuffle(obj) + ruby_version_is ""..."2.8" do + # keyword argument since 2.8 + it "attempts coercion via #to_hash" do + obj = mock('hash') + obj.should_receive(:to_hash).once.and_return({}) + [2, 3].shuffle(obj) + end end it "calls #rand on the Object passed by the :random key in the arguments Hash" do