I don\'t understand completely how named parameters in Ruby 2.0 work.
def test(var1, var2, var3)
puts \"#{var1} #{var2} #{var3}\"
end
test(var3:\"var3-ne
I think that the answer to your updated question can be explained with explicit examples. In the example below you have optional parameters in an explicit order:
def show_name_and_address(name="Someone", address="Somewhere")
puts "#{name}, #{address}"
end
show_name_and_address
#=> 'Someone, Somewhere'
show_name_and_address('Andy')
#=> 'Andy, Somewhere'
The named parameter approach is different. It still allows you to provide defaults but it allows the caller to determine which, if any, of the parameters to provide:
def show_name_and_address(name: "Someone", address: "Somewhere")
puts "#{name}, #{address}"
end
show_name_and_address
#=> 'Someone, Somewhere'
show_name_and_address(name: 'Andy')
#=> 'Andy, Somewhere'
show_name_and_address(address: 'USA')
#=> 'Someone, USA'
While it's true that the two approaches are similar when provided with no parameters, they differ when the user provides parameters to the method. With named parameters the caller can specify which parameter is being provided. Specifically, the last example (providing only the address) is not quite achievable in the first example; you can get similar results ONLY by supplying BOTH parameters to the method. This makes the named parameters approach much more flexible.
def test(a = 1, b: 2, c: 3)
p [a,b,c]
end
test #=> [1,2,3]
test 10 #=> [10,2,3]
test c:30 #=> [1,2,30] <- this is where named parameters become handy.
You can define the default value and the name of the parameter and then call the method the way you would call it if you had hash-based "named" parameters but without the need to define defaults in your method.
You would need this in your method for each "named parameter" if you were using a hash.
b = options_hash[:b] || 2
as in:
def test(a = 1, options_hash)
b = options_hash[:b] || 2
c = options_hash[:c] || 3
p [a,b,c]
end
You can define named parameters like
def test(var1: var1, var2: var2, var3: var3)
puts "#{var1} #{var2} #{var3}"
end
If you don't pass one of the parameters, then Ruby will complain about an undefined local variable or method
.
I agree with you that it's weird to require default values as the price for using named parameters, and evidently the Ruby maintainers agree with us! Ruby 2.1 will drop the default value requirement as of 2.1.0-preview1.
According to "Ruby 2.0.0 by Example" you must have defaults:
In Ruby 2.0.0, keyword arguments must have defaults, or else must be captured by **extra at the end.
As of Ruby 2.1.0, you no longer have to set default values for named parameters. If you omit the default value for a parameter, the caller will be required to provide it.
def concatenate(val1: 'default', val2:)
"#{val1} #{val2}"
end
concatenate(val2: 'argument')
#=> "default argument"
concatenate(val1: 'change')
#=> ArgumentError: missing keyword: val2
Given:
def test1(var1="default value123")
var1
end
def test2(var1:"default value123")
var1
end
They'll behave the same way when not passed an argument:
test1
#=> "default value123"
test2
#=> "default value123"
But they'll behave much differently when an argument is passed:
test1("something else")
#=> "something else"
test2("something else")
#=> ArgumentError: wrong number of arguments (1 for 0)
test1(var1: "something else")
#=> {:var1=>"something else"}
test2(var1: "something else")
#=> "something else"