Project

General

Profile

Actions

Backport #8072

closed

Method#arity for keyword arguments

Added by marcandre (Marc-Andre Lafortune) about 11 years ago. Updated about 10 years ago.


Description

I would expect the following two methods to have the same arity:

def old_way(req, options = {}); end
def new_way(req, **options); end

method(:new_way).arity # => 1, should be -2

Related issues 1 (0 open1 closed)

Related to Backport21 - Backport #9299: Required keyowrd arguments and arityClosedmatz (Yukihiro Matsumoto)Actions

Updated by Anonymous almost 11 years ago

+1

Ruby has outgrown #arity. Today, plain #arity should only return positive value,
when the function has only compulsory ordered arguments. If there are any other
arguments (optional ordered, named, splat-collected...), #arity should return a
negative value, meaning "Sorry, I give up, the negative integer I am returning
does not fully describe this function's arguments."

How about giving #arity an optional argument with terminology like in #parameters?

f = -> a, b, c=1, *d, e: 3, f: 4, **g {}
f.parameters
#=> [[:req, :a], [:req, :b], [:opt, :c], [:rest, :d], [:key, :e], [:key, :f], [:keyrest, :g]]
f.arity #=> -3
f.arity( :req ) #=> 2
f.arity( :opt ) #=> 1
f.arity( :rest ) #=> 1
f.arity( :key ) #=> 2
f.arity( :keyrest ) #=> 1

g = -> compulsory_ordered_argument, **splat_collected_named_arguments {}
g.arity #=> -2
g.arity( :req ) #=> 1
g.arity( :opt ) #=> 0
g.arity( :rest ) #=> 0
g.arity( :key ) #=> 0
g.arity( :keyrest ) #=> 1

I also think, that #arity behavior for lambdas and procs should be the same.

Actions #2

Updated by nobu (Nobuyoshi Nakada) over 10 years ago

  • Status changed from Open to Closed
  • % Done changed from 0 to 100

This issue was solved with changeset r44413.
Marc-Andre, thank you for reporting this issue.
Your contribution to Ruby is greatly appreciated.
May Ruby be with you.


proc.c: fix arity of rest keywords argument

  • proc.c (rb_iseq_min_max_arity): maximum argument is unlimited if
    having rest keywords argument. [ruby-core:53298] [Bug #8072]

Updated by nagachika (Tomoyuki Chikanaga) over 10 years ago

  • Backport set to 1.9.3: DONTNEED, 2.0.0: REQUIRED

Updated by marcandre (Marc-Andre Lafortune) over 10 years ago

  • Status changed from Closed to Open
  • Assignee changed from matz (Yukihiro Matsumoto) to naruse (Yui NARUSE)
  • Backport changed from 1.9.3: DONTNEED, 2.0.0: REQUIRED to 1.9.3: DONTNEED, 2.0.0: REQUIRED, 2.1.0: REQUIRED

I don't think this fix is correct. A method/proc having keyword arguments should be considered as having one optional argument, not infinitely many. Among other things:

proc{|options = {}|}.arity == proc{|**options|}.arity # => should be true

I've committed r44432 to fix this.

Actions #5

Updated by marcandre (Marc-Andre Lafortune) over 10 years ago

  • Tracker changed from Bug to Backport
  • Project changed from Ruby master to Backport21
  • Category deleted (core)
  • Target version deleted (2.1.0)
Actions #6

Updated by naruse (Yui NARUSE) over 10 years ago

  • Assignee changed from naruse (Yui NARUSE) to matz (Yukihiro Matsumoto)

About the behavior, the right return value is not clear for me.
It needs matz' decision.

Updated by naruse (Yui NARUSE) about 10 years ago

  • Status changed from Open to Feedback
  • Assignee changed from matz (Yukihiro Matsumoto) to marcandre (Marc-Andre Lafortune)

Updated by naruse (Yui NARUSE) about 10 years ago

  • Status changed from Feedback to Closed

Applied in changeset r45138.


merge revision(s) 44412,44413,44414,44420,44421: [Backport #9298]

test_method.rb, test_proc.rb: suppress warnings

* test/ruby/test_method.rb: suppress warnings in verbose mode.

* test/ruby/test_proc.rb: ditto.
* proc.c (rb_iseq_min_max_arity): maximum argument is unlimited if
  having rest keywords argument.  [ruby-core:53298] [Bug #8072]

* iseq.c (rb_iseq_parameters): push argument type symbol only for
  unnamed rest keywords argument.

* compile.c (iseq_set_arguments): set arg_keyword_check from
  nd_cflag, which is set by parser.  internal ID is used for
  unnamed keyword rest argument, which should be separated from no
  keyword check.

* iseq.c (rb_iseq_parameters): if no keyword check, keyword rest is
  present.

* parse.y (new_args_tail_gen): set keywords check to nd_cflag, which
  equals to that keyword rest is not present.
Actions

Also available in: Atom PDF

Like0
Like0Like0Like0Like0Like0Like0Like0Like0