Closed bryanrite closed 5 years ago
After a tiny bit of experimentation, something similar to:
# Changing
def m(a, b=nil, c=nil)
[a, b, c]
end
# into
def m(a_p=nil, b_p=nil, c_p=nil, a: nil, b: nil, c: nil)
%i[a b c].each do |x|
binding.local_variable_set(x, binding.local_variable_get(x).presence || binding.local_variable_get("#{x}_p"))
end
%i[a].each { |x| raise ArgumentError unless binding.local_variable_get(x).present? }
[a, b, c]
end
m(1,2,3)
m(a: 4, b: 5, c: 6)
m(1, a: 4, b: 5, c: 6)
m(1, b:5, c: 6)
m()
m(a: 4)
m(1)
m(b: 5)
Will work.
Some of the functionality released in 2.0.0 uses positional arguments, which are fine in some circumstances, but since a lot of these functions have optional parameters, keyword arguments provide a more readable and useable interface.
We will need to continue to support the positional arguments in 2.x, but we should update the methods and docs to prefer keyword arguments. I think these methods can be tweaked, using defaults and keywords after positionals, plus some presence checking to support the existing positional args, but prefer keyword args.
Consumer methods can be positional since they are a single, required parameter (and more of an interface than a callable method).