可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
This question already has an answer here:
-
No named parameters in Ruby?
4 answers
I wonder why named parameters don't work as I expect.
def my_method(var1, var2 = 1, var3 = 10)
puts var1, var2, var3
end
my_method(999, var3 = 123)
The output
999
123
10
instead of (at least, as I guess should be):
999
1
123
So, what should I do to use named parameters?
P.S. When I use the hash, it's not what I'm looking for yet:
def my_method(var1, vars = {var2: 1, var3: 10} )
puts var1, vars[:var2], vars[:var3]
end
my_method(999, var3: 123)
999
123
my_method(999, var2: 111, var3: 123)
999
111
123
my_method(999)
999
1
10
So I have to override each value of vars
or don't override them at all. Is there any more convenient way?
回答1:
In ruby my_method(999, var3 = 123)
means, assign var3
the value 123
and pass it to my_method
.
There is no concept of named parameters, however, you can use a hash as an argument to my_method
such as:
def my_method(args = {})
p "#{args[:a]}, #{args[:b]}, #{args[:c]}"
end
Then you can call it with:
my_method(b: 2, c: 3, a: 1)
which will print 1, 2, 3
, because b: 2, c: 3, a: 1
is inferred to be a hash by ruby. You can explicitly indicate the hash as well with:
my_method({b: 2, c: 3, a: 1})
回答2:
As pointed out, Ruby does not have keyword arguments (yet, they are coming in 2.0). To achieve what you are trying to do, an options
hash is a very common Ruby idiom.
def my_method(var1, options = {})
var2 = options.fetch(:var2, 1)
var3 = options.fetch(:var3, 10)
puts var1, var2, var3
end
my_method(999)
# => 999, 1, 10
my_method(999, var3: 123)
# => 999, 1, 123
my_method(999, var2: 111)
# => 999, 111, 10
my_method(999, var2: 111, var3: 123)
# => 999, 111, 123
my_method()
# => ArgumentError: wrong number of arguments (0 for 1)
Note that using options.fetch(:key, default)
rather than options[:key] || default
is frequently preferable because it allows you to explicitly specify falsy values (ie false
and nil
).
options = {x: nil, y: false}
x = options[:x] || 42 # sets x to 42
x = options.fetch(:x, 42) # sets x to nil
y = options[:y] || 43 # sets y to 43
y = options.fetch(:y, 43) # sets y to false
z = options[:z] || 44 # sets z to 44
z = options.fetch(:z, 44) # sets z to 44
You can even pass a block to fetch
which allows you to defer computation of the default value:
options.fetch(:x) { some_expensive_calculation }
# some_expensive_calculation is only called if necessary
回答3:
You can use this
def my_method(options = {})
puts options[:var1] || ''
puts options[:var2] || ''
puts options[:var3] || ''
end
call using
my_method(var1:999, var3: 123)
or
my_method(var1:999)
回答4:
You can also play with something like this:
def method(data)
defaults = {var2: 1, var3: 10}
(@var1, @var2, @var3) = defaults.merge(data).values_at(:var1, :var2, :var3)
p @var1, @var2, @var3
end
method(var1: 999, var3: 123)
回答5:
Ruby 2.0.0 is released, now you can use named parameters.
def my_method(var1, var2: 1, var3: 10)
puts var1, var2, var3
end
my_method(999, var3: 123)
The result:
999
1
123
Or another example:
def foo(str: "foo", num: 100)
[str, num]
end
p foo(str: 'buz', num: 1) #=> ['buz', 1]
p foo(str: 'bar') # => ['bar', 100]
p foo(num: 2) # => ["foo", 2]
p foo # => ['foo', 100]
p foo(bar: 'buz') # => ArgumentError