I would like to create a function that has optional arguments with default values
def my_function(a = nil, b=nil, c=500)
end
and call the function with the arguments I would like to specify only
my_function(b=100)
How do I accomplish this in Ruby 1.9.2?
Default arguments are easy to add, you simply assign them a default value with = ("equals") in the argument list. There's no limit to the number of arguments that you can make default. Let's take a look at the different ways we can call this method: greeting # > Hello, Ruby programmer.
In the code you posted, *args simply indicates that the method accepts a variable number of arguments in an array called args . It could have been called anything you want (following the Ruby naming rules, of course).
What are Optional Parameters? By definition, an Optional Parameter is a handy feature that enables programmers to pass less number of parameters to a function and assign a default value. Firstly, let us first understand what the word Optional Parameter means. Parameters are the names listed in the function definition.
The default values are used only when you don't pass any other arguments. This kind of parameters is useful when we have parameters that most of the time have same values. A sequence of arguments must correspond to a sequence of parameters.
Arguments are bound to parameters like this:
Proc
and bound to the block argumentraise
an ArgumentError
Here's an example:
def foo(mand1, mand2, opt1=:opt1, opt2=:opt2, *splat, mand3, mand4, &block)
p local_variables.map {|v| "#{v} = #{eval(v.to_s)}" }
end
foo 1, 2, 3
# ArgumentError: wrong number of arguments (3 for 4+)
foo 1, 2, 3, 4
# mand1 = 1
# mand2 = 2
# opt1 = opt1
# opt2 = opt2
# splat = []
# mand3 = 3
# mand4 = 4
# block =
foo 1, 2, 3, 4, 5
# mand1 = 1
# mand2 = 2
# opt1 = 3
# opt2 = opt2
# splat = []
# mand3 = 4
# mand4 = 5
# block =
foo 1, 2, 3, 4, 5, 6
# mand1 = 1
# mand2 = 2
# opt1 = 3
# opt2 = 4
# splat = []
# mand3 = 5
# mand4 = 6
# block =
foo 1, 2, 3, 4, 5, 6, 7
# mand1 = 1
# mand2 = 2
# opt1 = 3
# opt2 = 4
# splat = [5]
# mand3 = 6
# mand4 = 7
# block =
foo 1, 2, 3, 4, 5, 6, 7, 8 do end
# mand1 = 1
# mand2 = 2
# opt1 = 3
# opt2 = 4
# splat = [5, 6]
# mand3 = 7
# mand4 = 8
# block = #<Proc:0x007fdc732cb468@(pry):42>
So, as you can see both from step 3 above and from the example, you cannot do this, because optional parameters are bound left-to-right, but you want to specify the middle argument.
Note that this has implications on API design: you should design your parameter lists in such a way that the most "unstable" optional parameters, i.e. the ones that a user most likely wants to supply themselves, are furthest to the left.
Ruby 2.0 now has keyword arguments, which is exactly what you are looking for:
def foo(m1, m2, o1=:o1, o2=:o2, *s, m3, m4, key1: :key1, key2: :key2, **keys, &b)
puts local_variables.map {|v| "#{v} = #{eval(v.to_s)}" }
end
foo 1, 2, 3
# ArgumentError: wrong number of arguments (3 for 4+)
foo 1, 2, 3, 4
# m1 = 1
# m2 = 2
# o1 = o1
# o2 = o2
# s = []
# m3 = 3
# m4 = 4
# key1 = key1
# key2 = key2
# b =
# keys = {}
foo 1, 2, 3, 4, 5
# m1 = 1
# m2 = 2
# o1 = 3
# o2 = o2
# s = []
# m3 = 4
# m4 = 5
# key1 = key1
# key2 = key2
# b =
# keys = {}
foo 1, 2, 3, 4, 5, 6
# m1 = 1
# m2 = 2
# o1 = 3
# o2 = 4
# s = []
# m3 = 5
# m4 = 6
# key1 = key1
# key2 = key2
# b =
# keys = {}
foo 1, 2, 3, 4, 5, 6, 7
# m1 = 1
# m2 = 2
# o1 = 3
# o2 = 4
# s = [5]
# m3 = 6
# m4 = 7
# key1 = key1
# key2 = key2
# b =
# keys = {}
foo 1, 2, 3, 4, 5, 6, 7, 8
# m1 = 1
# m2 = 2
# o1 = 3
# o2 = 4
# s = [5, 6]
# m3 = 7
# m4 = 8
# key1 = key1
# key2 = key2
# b =
# keys = {}
foo 1, 2, 3, 4, 5, 6, 7, 8, key1: 9
# m1 = 1
# m2 = 2
# o1 = 3
# o2 = 4
# s = [5, 6]
# m3 = 7
# m4 = 8
# key1 = 9
# key2 = key2
# b =
# keys = {}
foo 1, 2, 3, 4, 5, 6, 7, 8, key1: 9, key2: 10
# m1 = 1
# m2 = 2
# o1 = 3
# o2 = 4
# s = [5, 6]
# m3 = 7
# m4 = 8
# key1 = 9
# key2 = 10
# b =
# keys = {}
foo 1, 2, 3, 4, 5, 6, 7, 8, key1: 9, key2: 10, key3: 11
# m1 = 1
# m2 = 2
# o1 = 3
# o2 = 4
# s = [5, 6]
# m3 = 7
# m4 = 8
# key1 = 9
# key2 = 10
# b =
# keys = {:key3=>11}
foo 1, 2, 3, 4, 5, 6, 7, 8, key1: 9, key2: 10, key3: 11, key4: 12 do end
# m1 = 1
# m2 = 2
# o1 = 3
# o2 = 4
# s = [5, 6]
# m3 = 7
# m4 = 8
# key1 = 9
# key2 = 10
# b = #<Proc:0x007fdc75135a48@(pry):77>
# keys = {:key3=>11, key4=>12}
You cannot do that (or something similar) in Ruby < 2.0. The best you could do is:
def my_function(h = {})
h[:c] ||= 500
# Use h[:a], h[:b], h[:c]
...
end
my_function(b: 100)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With