Project

General

Profile

Feature #15357 ยป proc-parameters-req-15357.patch

jeremyevans0 (Jeremy Evans), 08/28/2019 02:11 AM

View differences:

proc.c
/*
* call-seq:
* prc.parameters -> array
* prc.parameters(lambda: true) -> array
*
* Returns the parameter information of this proc.
* Returns the parameter information of this proc. If the lambda
* keyword is provided, treats the proc as a lambda if true and
* as a non-lambda if false.
*
* prc = proc{|x, y=42, *other|}
* prc.parameters #=> [[:opt, :x], [:opt, :y], [:rest, :other]]
* prc = lambda{|x, y=42, *other|}
* prc.parameters #=> [[:req, :x], [:opt, :y], [:rest, :other]]
* prc = proc{|x, y=42, *other|}
* prc.parameters(lambda: true) #=> [[:req, :x], [:opt, :y], [:rest, :other]]
*/
static VALUE
rb_proc_parameters(VALUE self)
rb_proc_parameters(int argc, VALUE *argv, VALUE self)
{
int is_proc;
const rb_iseq_t *iseq = rb_proc_get_iseq(self, &is_proc);
static ID keyword_ids[1];
VALUE opt, lambda;
VALUE kwargs[1];
int is_proc ;
const rb_iseq_t *iseq;
iseq = rb_proc_get_iseq(self, &is_proc);
if (!keyword_ids[0]) {
CONST_ID(keyword_ids[0], "lambda");
}
rb_scan_args(argc, argv, "0:", &opt);
if (!NIL_P(opt)) {
rb_get_kwargs(opt, keyword_ids, 0, 1, kwargs);
lambda = kwargs[0];
if (!NIL_P(lambda)) {
is_proc = !RTEST(lambda);
}
}
if (!iseq) {
return rb_unnamed_parameters(rb_proc_arity(self));
}
......
rb_define_method(rb_cProc, "<<", proc_compose_to_left, 1);
rb_define_method(rb_cProc, ">>", proc_compose_to_right, 1);
rb_define_method(rb_cProc, "source_location", rb_proc_location, 0);
rb_define_method(rb_cProc, "parameters", rb_proc_parameters, 0);
rb_define_method(rb_cProc, "parameters", rb_proc_parameters, -1);
/* Exceptions */
rb_eLocalJumpError = rb_define_class("LocalJumpError", rb_eStandardError);
spec/ruby/core/proc/parameters_spec.rb
proc {|x| }.parameters.first.first.should == :opt
end
ruby_version_is "2.7" do
it "sets the first element of each sub-Array to :req if argument would be required if a lambda if lambda keyword used" do
proc {|x| }.parameters(lambda: true).first.first.should == :req
proc {|y,*x| }.parameters(lambda: true).first.first.should == :req
end
it "regards named parameters in procs as required if lambda keyword used" do
proc {|x| }.parameters(lambda: true).first.first.should == :req
end
end
it "regards optional keyword parameters in procs as optional" do
proc {|x: :y| }.parameters.first.first.should == :key
end
test/ruby/test_proc.rb
assert_empty(pr.parameters.map{|_,n|n}.compact)
end
def test_parameters_lambda
assert_equal([], proc {}.parameters(lambda: true))
assert_equal([], proc {||}.parameters(lambda: true))
assert_equal([[:req, :a]], proc {|a|}.parameters(lambda: true))
assert_equal([[:req, :a], [:req, :b]], proc {|a, b|}.parameters(lambda: true))
assert_equal([[:opt, :a], [:block, :b]], proc {|a=:a, &b|}.parameters(lambda: true))
assert_equal([[:req, :a], [:opt, :b]], proc {|a, b=:b|}.parameters(lambda: true))
assert_equal([[:rest, :a]], proc {|*a|}.parameters(lambda: true))
assert_equal([[:req, :a], [:rest, :b], [:block, :c]], proc {|a, *b, &c|}.parameters(lambda: true))
assert_equal([[:req, :a], [:rest, :b], [:req, :c]], proc {|a, *b, c|}.parameters(lambda: true))
assert_equal([[:req, :a], [:rest, :b], [:req, :c], [:block, :d]], proc {|a, *b, c, &d|}.parameters(lambda: true))
assert_equal([[:req, :a], [:opt, :b], [:rest, :c], [:req, :d], [:block, :e]], proc {|a, b=:b, *c, d, &e|}.parameters(lambda: true))
assert_equal([[:req], [:block, :b]], proc {|(a), &b|a}.parameters(lambda: true))
assert_equal([[:req, :a], [:req, :b], [:opt, :c], [:opt, :d], [:rest, :e], [:req, :f], [:req, :g], [:block, :h]], proc {|a,b,c=:c,d=:d,*e,f,g,&h|}.parameters(lambda: true))
pr = eval("proc{|"+"(_),"*30+"|}")
assert_empty(pr.parameters(lambda: true).map{|_,n|n}.compact)
end
def pm0() end
def pm1(a) end
def pm2(a, b) end
    (1-1/1)