Actions
Bug #12717
closedOptional argument treated as kwarg
Description
When you define a method with an optional argument and keyword arguments (whether explicitly or with options splat) the defaulted argument can not take a hash argument, instead it is interpreted as keyword arguments:
class Foo
def self.options(value = nil, **options)
puts value.inspect
puts options.inspect
end
def self.kwarg(value = nil, kw: nil)
puts value.inspect
puts kw.inspect
end
def self.splat(*args, kw: nil)
puts args.inspect
puts kw.inspect
end
end
Foo.options({})
# nil
# {}
Foo.kwarg({})
# nil
# nil
Foo.splat({})
# []
# nil
Foo.options({ key: :value })
# nil
# {:key=>:value}
Foo.kwarg({ key: :value })
# ArgumentError: unknown keyword: key
Foo.splat({ key: :value })
# ArgumentError: unknown keyword: key
I would expect the output to be:
Foo.options({})
# {}
# {}
Foo.kwarg({})
# {}
# nil
Foo.splat({})
# [{}]
# nil
Foo.options({ key: :value })
# {:key=>:value}
# {}
Foo.kwarg({ key: :value })
# {:key=>:value}
# nil
Foo.splat({ key: :value })
# [{:key=>:value}]
# nil
Updated by hsbt (Hiroshi SHIBATA) about 7 years ago
- Related to Feature #14183: "Real" keyword argument added
Updated by marcandre (Marc-Andre Lafortune) over 6 years ago
I believe this is as designed.
As I stated previously (https://bugs.ruby-lang.org/issues/11967#note-3), my understanding is that:
- after all mandatory unnamed arguments are filled
- if the last remaining argument is hash-like
- and all its keys are symbols
- and the method called uses keyword arguments => then that parameter is used for keyword arguments.
I believe we should close this issue.
Updated by marcandre (Marc-Andre Lafortune) over 6 years ago
- Has duplicate Bug #13336: Default Parameters don't work added
Updated by jeremyevans0 (Jeremy Evans) over 5 years ago
- Status changed from Open to Closed
With the changes in #14183:
Foo.options({})
# (irb):21: warning: The last argument for `options' (defined at (irb):6) is used as the keyword parameter
# nil
# {}
Foo.kwarg({})
# (irb):22: warning: The last argument for `kwarg' (defined at (irb):11) is used as the keyword parameter
# nil
# nil
Foo.splat({})
# (irb):23: warning: The last argument for `splat' (defined at (irb):16) is used as the keyword parameter
# []
# nil
Foo.options({ key: :value })
# (irb):24: warning: The last argument for `options' (defined at (irb):6) is used as the keyword parameter
# nil
# {:key=>:value}
Foo.kwarg({ key: :value })
# (irb):25: warning: The last argument for `kwarg' (defined at (irb):11) is used as the keyword parameter
# ArgumentError (unknown keyword: :key)
Foo.splat({ key: :value })
# (irb):26: warning: The last argument for `splat' (defined at (irb):16) is used as the keyword parameter
# ArgumentError (unknown keyword: :key)
In Ruby 3, the behavior will be:
Foo.options({})
# {}
# {}
Foo.kwarg({})
# {}
# nil
Foo.splat({})
# [{}]
# nil
Foo.options({ key: :value })
# {:key=>:value}
# {}
Foo.kwarg({ key: :value })
# {:key=>:value}
# nil
Foo.splat({ key: :value })
# [{:key=>:value}]
# nil
I'm going to close this now as the deprecation warnings for the cases where behavior will change in Ruby 3 have been added.
Actions
Like0
Like0Like0Like0Like0