diff options
| -rw-r--r-- | mrbgems/mruby-enum-ext/mrblib/enum.rb | 22 | ||||
| -rw-r--r-- | src/kernel.c | 19 | ||||
| -rw-r--r-- | test/t/kernel.rb | 9 |
3 files changed, 50 insertions, 0 deletions
diff --git a/mrbgems/mruby-enum-ext/mrblib/enum.rb b/mrbgems/mruby-enum-ext/mrblib/enum.rb index 2affe555f..0a18a3d35 100644 --- a/mrbgems/mruby-enum-ext/mrblib/enum.rb +++ b/mrbgems/mruby-enum-ext/mrblib/enum.rb @@ -25,15 +25,20 @@ module Enumerable ## # call-seq: # enum.drop_while {|arr| block } -> array + # enum.drop_while -> an_enumerator # # Drops elements up to, but not including, the first element for # which the block returns +nil+ or +false+ and returns an array # containing the remaining elements. # + # If no block is given, an enumerator is returned instead. + # # a = [1, 2, 3, 4, 5, 0] # a.drop_while {|i| i < 3 } #=> [3, 4, 5, 0] def drop_while(&block) + return to_enum :drop_while unless block_given? + ary, state = [], false self.each do |*val| state = true if !state and !block.call(*val) @@ -67,15 +72,19 @@ module Enumerable ## # call-seq: # enum.take_while {|arr| block } -> array + # enum.take_while -> an_enumerator # # Passes elements to the block until the block returns +nil+ or +false+, # then stops iterating and returns an array of all prior elements. # + # If no block is given, an enumerator is returned instead. # # a = [1, 2, 3, 4, 5, 0] # a.take_while {|i| i < 3 } #=> [1, 2] def take_while(&block) + return to_enum :take_while unless block_given? + ary = [] self.each do |*val| return ary unless block.call(*val) @@ -149,6 +158,7 @@ module Enumerable ## # call-seq: # enum.group_by {| obj | block } -> a_hash + # enum.group_by -> an_enumerator # # Returns a hash, which keys are evaluated result from the # block, and values are arrays of elements in <i>enum</i> @@ -157,6 +167,8 @@ module Enumerable # (1..6).group_by {|i| i%3} #=> {0=>[3, 6], 1=>[1, 4], 2=>[2, 5]} def group_by(&block) + return to_enum :group_by unless block_given? + h = {} self.each do |*val| key = block.call(*val) @@ -169,10 +181,16 @@ module Enumerable ## # call-seq: # enum.sort_by { |obj| block } -> array + # enum.sort_by -> an_enumerator # # Sorts <i>enum</i> using a set of keys generated by mapping the # values in <i>enum</i> through the given block. + # + # If no block is given, an enumerator is returned instead. + def sort_by(&block) + return to_enum :sort_by unless block_given? + ary = [] orig = [] self.each_with_index{|e, i| @@ -393,6 +411,8 @@ module Enumerable # %w(albatross dog horse).minmax_by { |x| x.length } #=> ["dog", "albatross"] def minmax_by(&block) + return to_enum :minmax_by unless block_given? + max = nil max_cmp = nil min = nil @@ -522,6 +542,8 @@ module Enumerable # def reverse_each(&block) + return to_enum :reverse_each unless block_given? + ary = self.to_a i = ary.size - 1 while i>=0 diff --git a/src/kernel.c b/src/kernel.c index e637a53b1..afba3e857 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -1098,6 +1098,24 @@ mrb_obj_singleton_methods_m(mrb_state *mrb, mrb_value self) } static mrb_value +mod_define_singleton_method(mrb_state *mrb, mrb_value self) +{ + struct RProc *p; + mrb_sym mid; + mrb_value blk = mrb_nil_value(); + + mrb_get_args(mrb, "n&", &mid, &blk); + if (mrb_nil_p(blk)) { + mrb_raise(mrb, E_ARGUMENT_ERROR, "no block given"); + } + p = (struct RProc*)mrb_obj_alloc(mrb, MRB_TT_PROC, mrb->proc_class); + mrb_proc_copy(p, mrb_proc_ptr(blk)); + p->flags |= MRB_PROC_STRICT; + mrb_define_method_raw(mrb, mrb_class_ptr(mrb_singleton_class(mrb, self)), mid, p); + return mrb_symbol_value(mid); +} + +static mrb_value mrb_obj_ceqq(mrb_state *mrb, mrb_value self) { mrb_value v; @@ -1165,6 +1183,7 @@ mrb_init_kernel(mrb_state *mrb) mrb_define_method(mrb, krn, "respond_to?", obj_respond_to, MRB_ARGS_ANY()); /* 15.3.1.3.43 */ mrb_define_method(mrb, krn, "send", mrb_f_send, MRB_ARGS_ANY()); /* 15.3.1.3.44 */ mrb_define_method(mrb, krn, "singleton_methods", mrb_obj_singleton_methods_m, MRB_ARGS_OPT(1)); /* 15.3.1.3.45 */ + mrb_define_method(mrb, krn, "define_singleton_method", mod_define_singleton_method, MRB_ARGS_ANY()); mrb_define_method(mrb, krn, "to_s", mrb_any_to_s, MRB_ARGS_NONE()); /* 15.3.1.3.46 */ mrb_define_method(mrb, krn, "__case_eqq", mrb_obj_ceqq, MRB_ARGS_REQ(1)); /* internal */ diff --git a/test/t/kernel.rb b/test/t/kernel.rb index c8913c718..c6b65ddf7 100644 --- a/test/t/kernel.rb +++ b/test/t/kernel.rb @@ -542,6 +542,15 @@ assert('Kernel#__method__') do assert_equal(:m2, c.new.m2) end +assert('Kernel#define_singleton_method') do + o = Object.new + ret = o.define_singleton_method(:test_method) do + :singleton_method_ok + end + assert_equal :test_method, ret + assert_equal :singleton_method_ok, o.test_method +end + assert('stack extend') do def recurse(count, stop) return count if count > stop |
