summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--mrbgems/mruby-enum-ext/mrblib/enum.rb22
-rw-r--r--src/kernel.c19
-rw-r--r--test/t/kernel.rb9
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