Project

General

Profile

Feature #6284 » 0001-proc.c-Implement-Proc-for-Proc-composition.patch

mudge (Paul Mucur), 12/30/2015 12:27 PM

View differences:

proc.c
return proc_curry(argc, argv, proc);
}
static VALUE
compose(VALUE dummy, VALUE args, int argc, VALUE *argv, VALUE passed_proc)
{
VALUE f, g, fargs;
f = RARRAY_AREF(args, 0);
g = RARRAY_AREF(args, 1);
fargs = rb_ary_new3(1, rb_proc_call_with_block(g, argc, argv, passed_proc));
return rb_proc_call(f, fargs);
}
/*
* call-seq:
* prc * g -> a_proc
*
* Returns a proc that is the composition of this proc 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 proc with the result.
*
* f = proc {|x| x * 2 }
* g = proc {|x, y| x + y }
* h = f * g
* p h.call(1, 2) #=> 6
*/
static VALUE
proc_compose(VALUE self, VALUE g)
{
VALUE proc, args;
rb_proc_t *procp;
int is_lambda;
if (!rb_obj_is_method(g) && !rb_obj_is_proc(g)) {
rb_raise(rb_eTypeError,
"wrong argument type %s (expected Proc/Method)",
rb_obj_classname(g));
}
if (rb_obj_is_method(g)) {
g = method_to_proc(g);
}
args = rb_ary_new3(2, self, g);
GetProcPtr(self, procp);
is_lambda = procp->is_lambda;
proc = rb_proc_new(compose, args);
GetProcPtr(proc, procp);
procp->is_lambda = is_lambda;
return proc;
}
/*
* Document-class: LocalJumpError
*
......
rb_define_method(rb_cProc, "lambda?", rb_proc_lambda_p, 0);
rb_define_method(rb_cProc, "binding", proc_binding, 0);
rb_define_method(rb_cProc, "curry", proc_curry, -1);
rb_define_method(rb_cProc, "*", proc_compose, 1);
rb_define_method(rb_cProc, "source_location", rb_proc_location, 0);
rb_define_method(rb_cProc, "parameters", rb_proc_parameters, 0);
test/ruby/test_proc.rb
e.each {}
EOS
end
def test_compose
f = proc{|x| x * 2}
g = proc{|x| x + 1}
h = f * g
assert_equal(6, h.call(2))
end
def test_compose_with_multiple_args
f = proc{|x| x * 2}
g = proc{|x, y| x + y}
h = f * g
assert_equal(6, h.call(1, 2))
end
def test_compose_with_block
f = proc{|x| x * 2}
g = proc{|&blk| blk.call(1) }
h = f * g
assert_equal(8, h.call { |x| x + 3 })
end
def test_compose_with_lambda
f = lambda{|x| x * 2}
g = lambda{|x| x}
h = f * g
assert(h.lambda?)
end
def test_compose_with_method
f = proc{|x| x * 2}
c = Class.new {
def g(x) x + 1 end
}
g = c.new.method(:g)
h = f * g
assert_equal(6, h.call(2))
end
def test_compose_with_nonproc_or_method
f = proc{|x| x * 2}
assert_raise(TypeError) {
f * 5
}
end
end
(1-1/3)