ruby-changes:14687
From: matz <ko1@a...>
Date: Tue, 2 Feb 2010 17:58:51 +0900 (JST)
Subject: [ruby-changes:14687] Ruby:r26540 (trunk): * enum.c (enum_each_entry): new method #each_entry to pack values
matz 2010-02-02 17:54:52 +0900 (Tue, 02 Feb 2010) New Revision: 26540 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=26540 Log: * enum.c (enum_each_entry): new method #each_entry to pack values from yield into an array. * lib/set.rb (Set#merge): use Enumerable#each_entry to implement Set compatible to 1.8 behavior. [ruby-core:27985] * lib/set.rb: replace is_a?(Enumerable) with respond_to?(:each) for duck typing. * lib/set.rb (SortedSet#add): typo fixed. Modified files: trunk/ChangeLog trunk/enum.c trunk/lib/set.rb trunk/test/ruby/test_enum.rb Index: ChangeLog =================================================================== --- ChangeLog (revision 26539) +++ ChangeLog (revision 26540) @@ -1,3 +1,15 @@ +Tue Feb 2 14:30:27 2010 Yukihiro Matsumoto <matz@r...> + + * enum.c (enum_each_entry): new method #each_entry to pack values + from yield into an array. + + * lib/set.rb (Set#merge): use Enumerable#each_entry to implement + Set compatible to 1.8 behavior. [ruby-core:27985] + + * lib/set.rb: replace is_a?(Enumerable) with respond_to?(:each) + for duck typing. + + * lib/set.rb (SortedSet#add): typo fixed. Tue Feb 2 11:13:56 2010 Nobuyoshi Nakada <nobu@r...> * lib/delegate.rb (Delegator#marshal_dump): exclude Index: enum.c =================================================================== --- enum.c (revision 26539) +++ enum.c (revision 26540) @@ -1618,6 +1618,46 @@ static VALUE +each_val_i(VALUE i, VALUE p, int argc, VALUE *argv) +{ + VALUE *memo = (VALUE *)p; + + ENUM_WANT_SVALUE(); + rb_yield(i); + return Qnil; +} + +/* + * call-seq: + * enum.each_entry {|obj| block} => enum + * + * Calls <i>block</i> once for each element in <i>self</i>, passing that + * element as a parameter, converting multiple values from yield to an + * array. + * + * class Foo + * include Enumerable + * def each + * yield 1 + * yield 1,2 + * end + * end + * Foo.new.each_entry{|o| print o, " -- "} + * + * produces: + * + * 1 -- [1, 2] -- + */ + +static VALUE +enum_each_entry(int argc, VALUE *argv, VALUE obj) +{ + RETURN_ENUMERATOR(obj, argc, argv); + rb_block_call(obj, id_each, argc, argv, each_val_i, 0); + return obj; +} + +static VALUE zip_ary(VALUE val, NODE *memo, int argc, VALUE *argv) { volatile VALUE result = memo->u1.value; @@ -2435,6 +2475,7 @@ rb_define_method(rb_mEnumerable, "include?", enum_member, 1); rb_define_method(rb_mEnumerable, "each_with_index", enum_each_with_index, -1); rb_define_method(rb_mEnumerable, "reverse_each", enum_reverse_each, -1); + rb_define_method(rb_mEnumerable, "each_entry", enum_each_entry, -1); rb_define_method(rb_mEnumerable, "zip", enum_zip, -1); rb_define_method(rb_mEnumerable, "take", enum_take, 1); rb_define_method(rb_mEnumerable, "take_while", enum_take_while, 0); Index: lib/set.rb =================================================================== --- lib/set.rb (revision 26539) +++ lib/set.rb (revision 26540) @@ -70,8 +70,8 @@ enum.nil? and return if block - enum.is_a?(Enumerable) or raise ArgumentError, "value must be enumerable" - enum.each { |o| add(block[o]) } + enum.respond_to?(:each) or raise ArgumentError, "value must be enumerable" + enum.each_entry { |o| add(block[o]) } else merge(enum) end @@ -123,9 +123,9 @@ if enum.class == self.class @hash.replace(enum.instance_eval { @hash }) else - enum.is_a?(Enumerable) or raise ArgumentError, "value must be enumerable" + enum.respond_to?(:each) or raise ArgumentError, "value must be enumerable" clear - enum.each { |o| add(o) } + enum.each_entry { |o| add(o) } end self @@ -281,8 +281,8 @@ if enum.instance_of?(self.class) @hash.update(enum.instance_variable_get(:@hash)) else - enum.is_a?(Enumerable) or raise ArgumentError, "value must be enumerable" - enum.each { |o| add(o) } + enum.respond_to?(:each) or raise ArgumentError, "value must be enumerable" + enum.each_entry { |o| add(o) } end self @@ -291,8 +291,8 @@ # Deletes every element that appears in the given enumerable object # and returns self. def subtract(enum) - enum.is_a?(Enumerable) or raise ArgumentError, "value must be enumerable" - enum.each { |o| delete(o) } + enum.respond_to?(:each) or raise ArgumentError, "value must be enumerable" + enum.each_entry { |o| delete(o) } self end @@ -314,9 +314,9 @@ # Returns a new set containing elements common to the set and the # given enumerable object. def &(enum) - enum.is_a?(Enumerable) or raise ArgumentError, "value must be enumerable" + enum.respond_to?(:each) or raise ArgumentError, "value must be enumerable" n = self.class.new - enum.each { |o| n.add(o) if include?(o) } + enum.each_entry { |o| n.add(o) if include?(o) } n end alias intersection & ## @@ -514,7 +514,7 @@ end def add(o) - o.respond_to?(:<=>) or raise ArgumentError, "value must repond to <=>" + o.respond_to?(:<=>) or raise ArgumentError, "value must respond to <=>" super end alias << add @@ -642,16 +642,16 @@ # end # # def replace(enum) -# enum.is_a?(Enumerable) or raise ArgumentError, "value must be enumerable" +# enum.respond_to?(:each) or raise ArgumentError, "value must be enumerable" # clear -# enum.each { |o| add(o) } +# enum.each_entry { |o| add(o) } # # self # end # # def merge(enum) -# enum.is_a?(Enumerable) or raise ArgumentError, "value must be enumerable" -# enum.each { |o| add(o) } +# enum.respond_to?(:each) or raise ArgumentError, "value must be enumerable" +# enum.each_entry { |o| add(o) } # # self # end Index: test/ruby/test_enum.rb =================================================================== --- test/ruby/test_enum.rb (revision 26539) +++ test/ruby/test_enum.rb (revision 26540) @@ -219,6 +219,18 @@ assert_equal([55, 3628800], ret) end + class Foo + include Enumerable + def each + yield 1 + yield 1,2 + end + end + + def test_each_entry + assert_equal([1, [1, 2]], Foo.new.each_entry.to_a) + end + def test_zip assert_equal([[1,1],[2,2],[3,3],[1,1],[2,2]], @obj.zip(@obj)) a = [] -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/