summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--proc.c25
-rw-r--r--test/ruby/test_method.rb34
2 files changed, 59 insertions, 0 deletions
diff --git a/proc.c b/proc.c
index efff796499..3c3544ecf6 100644
--- a/proc.c
+++ b/proc.c
@@ -3100,6 +3100,30 @@ proc_compose(VALUE self, VALUE g)
}
/*
+ * call-seq:
+ * meth * g -> a_proc
+ *
+ * Returns a proc that is the composition of this method and the given proc <i>g</i>.
+ * The returned proc takes a variable number of arguments, calls <i>g</i> with them
+ * then calls this method with the result.
+ *
+ * def f(x)
+ * x * 2
+ * end
+ *
+ * f = self.method(:f)
+ * g = proc {|x, y| x + y }
+ * h = f * g
+ * p h.call(1, 2) #=> 6
+ */
+static VALUE
+rb_method_compose(VALUE self, VALUE g)
+{
+ VALUE proc = method_to_proc(self);
+ return proc_compose(proc, g);
+}
+
+/*
* Document-class: LocalJumpError
*
* Raised when Ruby can't yield as requested.
@@ -3222,6 +3246,7 @@ Init_Proc(void)
rb_define_method(rb_cMethod, "call", rb_method_call, -1);
rb_define_method(rb_cMethod, "===", rb_method_call, -1);
rb_define_method(rb_cMethod, "curry", rb_method_curry, -1);
+ rb_define_method(rb_cMethod, "*", rb_method_compose, 1);
rb_define_method(rb_cMethod, "[]", rb_method_call, -1);
rb_define_method(rb_cMethod, "arity", method_arity_m, 0);
rb_define_method(rb_cMethod, "inspect", method_inspect, 0);
diff --git a/test/ruby/test_method.rb b/test/ruby/test_method.rb
index fe0171dd57..80a2669633 100644
--- a/test/ruby/test_method.rb
+++ b/test/ruby/test_method.rb
@@ -1040,4 +1040,38 @@ class TestMethod < Test::Unit::TestCase
assert_operator(0.method(:<), :===, 5)
assert_not_operator(0.method(:<), :===, -5)
end
+
+ def test_compose_with_method
+ c = Class.new {
+ def f(x) x * 2 end
+ def g(x) x + 1 end
+ }
+ f = c.new.method(:f)
+ g = c.new.method(:g)
+ h = f * g
+
+ assert_equal(6, h.call(2))
+ end
+
+ def test_compose_with_proc
+ c = Class.new {
+ def f(x) x * 2 end
+ }
+ f = c.new.method(:f)
+ g = proc {|x| x + 1}
+ h = f * g
+
+ assert_equal(6, h.call(2))
+ end
+
+ def test_compose_with_nonproc_or_method
+ c = Class.new {
+ def f(x) x * 2 end
+ }
+ f = c.new.method(:f)
+
+ assert_raise(TypeError) {
+ f * 5
+ }
+ end
end