summaryrefslogtreecommitdiff
path: root/proc.c
diff options
context:
space:
mode:
authorJeremy Evans <code@jeremyevans.net>2019-08-27 18:38:48 -0700
committerJeremy Evans <code@jeremyevans.net>2022-03-17 11:52:02 -0700
commitb6804d62f822237e136e698e006c913df9990ec2 (patch)
tree49fb54048952f0ccd8a1e026c28688b025b68be3 /proc.c
parent29b68b89a0c0ea7de46c058fab746550398151f0 (diff)
Make Proc#parameters support lambda keyword for returning parameters as if lambda
This makes it easier to use Proc#parameters to build wrappers. Implements [Feature #15357]
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/5677
Diffstat (limited to 'proc.c')
-rw-r--r--proc.c39
1 files changed, 33 insertions, 6 deletions
diff --git a/proc.c b/proc.c
index aa6f31f294..4a4ba70c87 100644
--- a/proc.c
+++ b/proc.c
@@ -1415,19 +1415,46 @@ rb_unnamed_parameters(int arity)
/*
* call-seq:
- * prc.parameters -> array
+ * prc.parameters(lambda: nil) -> array
*
- * Returns the parameter information of this proc.
+ * Returns the parameter information of this proc. If the lambda
+ * keyword is provided and not nil, 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]]
+ * prc = lambda{|x, y=42, *other|}
+ * prc.parameters(lamdba: false) #=> [[:opt, :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));
}
@@ -4248,7 +4275,7 @@ Init_Proc(void)
rb_define_method(rb_cProc, "==", proc_eq, 1);
rb_define_method(rb_cProc, "eql?", proc_eq, 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);
rb_define_method(rb_cProc, "ruby2_keywords", proc_ruby2_keywords, 0);
// rb_define_method(rb_cProc, "isolate", rb_proc_isolate, 0); is not accepted.