ruby-changes:62113
From: Takashi <ko1@a...>
Date: Sat, 4 Jul 2020 01:52:51 +0900 (JST)
Subject: [ruby-changes:62113] f3a0d7a203 (master): Rewrite Kernel#tap with Ruby (#3281)
https://git.ruby-lang.org/ruby.git/commit/?id=f3a0d7a203 From f3a0d7a2035e9f5e0c70effd55732607e3def263 Mon Sep 17 00:00:00 2001 From: Takashi Kokubun <takashikkbn@g...> Date: Fri, 3 Jul 2020 09:52:35 -0700 Subject: Rewrite Kernel#tap with Ruby (#3281) * Rewrite Kernel#tap with Ruby This was good for VM too, but of course my intention is to unblock JIT's inlining of a block over yield (inlining invokeyield has not been committed though). * Fix test_settracefunc About the :tap deletions, the :tap events are actually traced (we already have a TracePoint test for builtin methods), but it's filtered out by tp.path == "xyzzy" (it became "<internal:kernel>"). We could trace tp.path == "<internal:kernel>" cases too, but the lineno is impacted by kernel.rb changes and I didn't want to make it fragile for kernel.rb lineno changes. diff --git a/benchmark/kernel_tap.yml b/benchmark/kernel_tap.yml new file mode 100644 index 0000000..4dcbb31 --- /dev/null +++ b/benchmark/kernel_tap.yml @@ -0,0 +1,6 @@ https://github.com/ruby/ruby/blob/trunk/benchmark/kernel_tap.yml#L1 +prelude: | + obj = Object.new + x = nil +benchmark: + kernel_tap: obj.tap { |o| x = o } +loop_count: 20000000 diff --git a/kernel.rb b/kernel.rb index d00ba3a..3404053 100644 --- a/kernel.rb +++ b/kernel.rb @@ -48,6 +48,28 @@ module Kernel https://github.com/ruby/ruby/blob/trunk/kernel.rb#L48 Primitive.rb_obj_clone2(freeze) end + # + # call-seq: + # obj.tap {|x| block } -> obj + # + # Yields self to the block, and then returns self. + # The primary purpose of this method is to "tap into" a method chain, + # in order to perform operations on intermediate results within the chain. + # + # (1..10) .tap {|x| puts "original: #{x}" } + # .to_a .tap {|x| puts "array: #{x}" } + # .select {|x| x.even? } .tap {|x| puts "evens: #{x}" } + # .map {|x| x*x } .tap {|x| puts "squares: #{x}" } + # + #-- + # \private + #++ + # + def tap + yield(self) + self + end + module_function # diff --git a/object.c b/object.c index c4a0d3c..4718fad 100644 --- a/object.c +++ b/object.c @@ -938,31 +938,6 @@ rb_class_search_ancestor(VALUE cl, VALUE c) https://github.com/ruby/ruby/blob/trunk/object.c#L938 return class_search_ancestor(cl, RCLASS_ORIGIN(c)); } -/** - * call-seq: - * obj.tap {|x| block } -> obj - * - * Yields self to the block, and then returns self. - * The primary purpose of this method is to "tap into" a method chain, - * in order to perform operations on intermediate results within the chain. - * - * (1..10) .tap {|x| puts "original: #{x}" } - * .to_a .tap {|x| puts "array: #{x}" } - * .select {|x| x.even? } .tap {|x| puts "evens: #{x}" } - * .map {|x| x*x } .tap {|x| puts "squares: #{x}" } - * - *-- - * \private - *++ - */ - -VALUE -rb_obj_tap(VALUE obj) -{ - rb_yield(obj); - return obj; -} - /* * Document-method: inherited @@ -4638,7 +4613,6 @@ InitVM_Object(void) https://github.com/ruby/ruby/blob/trunk/object.c#L4613 rb_define_method(rb_mKernel, "instance_of?", rb_obj_is_instance_of, 1); rb_define_method(rb_mKernel, "kind_of?", rb_obj_is_kind_of, 1); rb_define_method(rb_mKernel, "is_a?", rb_obj_is_kind_of, 1); - rb_define_method(rb_mKernel, "tap", rb_obj_tap, 0); rb_define_global_function("sprintf", f_sprintf, -1); rb_define_global_function("format", f_sprintf, -1); diff --git a/test/ruby/test_settracefunc.rb b/test/ruby/test_settracefunc.rb index 3aaa34f..f688e5a 100644 --- a/test/ruby/test_settracefunc.rb +++ b/test/ruby/test_settracefunc.rb @@ -485,8 +485,6 @@ class TestSetTraceFunc < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_settracefunc.rb#L485 [:c_call, 4, 'xyzzy', Integer, :times, 1, :outer, :nothing], [:line, 4, 'xyzzy', self.class, method, self, nil, :nothing], [:line, 5, 'xyzzy', self.class, method, self, :inner, :nothing], - [:c_call, 5, 'xyzzy', Kernel, :tap, self, :inner, :nothing], - [:c_return, 5, "xyzzy", Kernel, :tap, self, :inner, self], [:c_return, 4, "xyzzy", Integer, :times, 1, :outer, 1], [:line, 7, 'xyzzy', self.class, method, self, :outer, :nothing], [:c_call, 7, "xyzzy", Class, :inherited, Object, :outer, :nothing], @@ -512,8 +510,6 @@ class TestSetTraceFunc < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_settracefunc.rb#L510 [:call, 13, "xyzzy", xyzzy.class, :bar, xyzzy, nil, :nothing], [:line, 14, "xyzzy", xyzzy.class, :bar, xyzzy, nil, :nothing], [:line, 15, "xyzzy", xyzzy.class, :bar, xyzzy, :XYZZY_bar, :nothing], - [:c_call, 15, "xyzzy", Kernel, :tap, xyzzy, :XYZZY_bar, :nothing], - [:c_return,15, "xyzzy", Kernel, :tap, xyzzy, :XYZZY_bar, xyzzy], [:return, 16, "xyzzy", xyzzy.class, :bar, xyzzy, :XYZZY_bar, xyzzy], [:return, 12, "xyzzy", xyzzy.class, :foo, xyzzy, :XYZZY_foo, xyzzy], [:line, 20, "xyzzy", TestSetTraceFunc, method, self, :outer, :nothing], @@ -610,8 +606,6 @@ class TestSetTraceFunc < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_settracefunc.rb#L606 [:c_call, 4, 'xyzzy', Integer, :times, 1, :outer, :nothing], [:line, 4, 'xyzzy', self.class, method, self, nil, :nothing], [:line, 5, 'xyzzy', self.class, method, self, :inner, :nothing], - [:c_call, 5, 'xyzzy', Kernel, :tap, self, :inner, :nothing], - [:c_return, 5, "xyzzy", Kernel, :tap, self, :inner, self], [:c_return, 4, "xyzzy", Integer, :times, 1, :outer, 1], [:line, 7, 'xyzzy', self.class, method, self, :outer, :nothing], [:c_call, 7, "xyzzy", Class, :inherited, Object, :outer, :nothing], @@ -637,8 +631,6 @@ class TestSetTraceFunc < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_settracefunc.rb#L631 [:call, 13, "xyzzy", xyzzy.class, :bar, xyzzy, nil, :nothing], [:line, 14, "xyzzy", xyzzy.class, :bar, xyzzy, nil, :nothing], [:line, 15, "xyzzy", xyzzy.class, :bar, xyzzy, :XYZZY_bar, :nothing], - [:c_call, 15, "xyzzy", Kernel, :tap, xyzzy, :XYZZY_bar, :nothing], - [:c_return,15, "xyzzy", Kernel, :tap, xyzzy, :XYZZY_bar, xyzzy], [:return, 16, "xyzzy", xyzzy.class, :bar, xyzzy, :XYZZY_bar, xyzzy], [:return, 12, "xyzzy", xyzzy.class, :foo, xyzzy, :XYZZY_foo, xyzzy], [:line, 20, "xyzzy", TestSetTraceFunc, method, self, :outer, :nothing], @@ -1685,7 +1677,7 @@ class TestSetTraceFunc < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_settracefunc.rb#L1677 TracePoint.new(:return, &capture_events).enable{ o.alias_m } - assert_equal [[:return, :m, :alias_m]], events + assert_equal [[:return, :tap, :tap], [:return, :m, :alias_m]], events events.clear o = Class.new{ @@ -1709,13 +1701,13 @@ class TestSetTraceFunc < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_settracefunc.rb#L1701 events.clear o = Class.new{ - alias alias_tap tap - define_method(:m){alias_tap{return}} + alias alias_singleton_class singleton_class + define_method(:m){alias_singleton_class} }.new TracePoint.new(:c_return, &capture_events).enable{ o.m } - assert_equal [[:c_return, :tap, :alias_tap]], events + assert_equal [[:c_return, :singleton_class, :alias_singleton_class]], events events.clear c = Class.new{ -- cgit v0.10.2 -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/