1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

proc.c: Implement Method#* for Method composition

* proc.c (rb_method_compose): Implement Method#* for Method composition,
  which delegates to Proc#*.

* test/ruby/test_method.rb: Add test cases for Method composition.

From: Paul Mucur <mudge@mudge.name>

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@65912 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
nobu 2018-11-22 05:51:41 +00:00
parent a43e967b8d
commit 4eaf22cc3f
2 changed files with 59 additions and 0 deletions

25
proc.c
View file

@ -3099,6 +3099,30 @@ proc_compose(VALUE self, VALUE g)
return proc;
}
/*
* 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
*
@ -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);

View file

@ -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