我完全不了解Ruby 2.0中的命名参数是如何工作的。
def test(var1, var2, var3)
puts "#{var1} #{var2} #{var3}"
end
test(var3:"var3-new", var1: 1111, var2: 2222) #wrong number of arguments (1 for 3) (ArgumentError)
它被视为哈希。而且非常有趣,因为在Ruby 2.0中使用命名参数我必须为它们设置默认值:
def test(var1: "var1", var2: "var2", var3: "var3")
puts "#{var1} #{var2} #{var3}"
end
test(var3:"var3-new", var1: 1111, var2: 2222) # ok => 1111 2222 var3-new
与Ruby之前使用默认参数值的行为非常相似:
def test(var1="var1", var2="var2", var3="var3")
puts "#{var1} #{var2} #{var3}"
end
test(var3:"var3-new", var1: 1111, var2: 2222) # ok but ... {:var3=>"var3-new", :var1=>1111, :var2=>2222} var2 var3
我知道为什么会这样,几乎是如何运作的。
但我只是好奇,必须如果我使用命名参数,我会使用参数的默认值吗?
并且,有人可以告诉我这两者之间有什么区别吗?
def test1(var1="default value123")
#.......
end
def test1(var1:"default value123")
#.......
end
答案 0 :(得分:34)
我认为您的更新问题的答案可以通过明确的示例来解释。在下面的示例中,您有一个显式顺序的可选参数:
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'
命名参数方法不同。它仍允许您提供默认值,但它允许调用者确定要提供的参数(如果有):
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'
虽然这两种方法在没有参数的情况下是相似的,但是当用户为方法提供参数时它们会有所不同。使用命名参数,调用者可以指定提供哪个参数。具体地说,在第一个例子中,最后一个例子(只提供地址)是不太可能实现的;只有通过向方法提供BOTH参数才能获得类似的结果。这使命名参数更加灵活。
答案 1 :(得分:16)
首先,您发布的最后一个示例具有误导性。我完全不同意这种行为与之前的行为类似。最后一个示例将参数hash in作为第一个可选参数传递,这是另一回事!
如果您不想使用默认值,可以使用nil
。
如果您想阅读好的文章,请参阅“Ruby 2 Keyword Arguments”。
答案 2 :(得分:13)
我同意你的看法,将默认值作为使用命名参数的价格是很奇怪的,显然Ruby维护者同意我们的意见! Ruby 2.1将drop the default value requirement as of 2.1.0-preview1。
答案 3 :(得分:10)
从Ruby 2.1.0开始,您不再需要为命名参数设置默认值。如果省略参数的默认值,则需要调用者提供它。
def concatenate(val1: 'default', val2:)
"#{val1} #{val2}"
end
concatenate(val2: 'argument')
#=> "default argument"
concatenate(val1: 'change')
#=> ArgumentError: missing keyword: val2
假设:
def test1(var1="default value123")
var1
end
def test2(var1:"default value123")
var1
end
未传递参数时,他们的行为方式相同:
test1
#=> "default value123"
test2
#=> "default value123"
但是当一个论点被传递时,他们的表现会大不相同:
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"
答案 4 :(得分:5)
这在所有其他答案中都有,但我想提取这个本质。
有四种参数:
*
定义函数时,在关键字参数之前指定位置参数,在可选参数之前指定必需参数。
Required Optional
Positional | def PR(a) | def PO(a=1) |
Keyword | def KR(a:) | def KO(a:1) |
编辑:必需的关键字参数(没有默认值)是Ruby 2.1.0中的新参数,正如其他人所提到的那样。
答案 5 :(得分:2)
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.
您可以定义参数的默认值和名称,然后如果您有基于哈希的“命名”参数但无需在方法中定义默认值,则可以按照调用它的方式调用方法。
如果使用哈希值,则在每个“命名参数”的方法中都需要这个。
b = options_hash[:b] || 2
如:
def test(a = 1, options_hash)
b = options_hash[:b] || 2
c = options_hash[:c] || 3
p [a,b,c]
end
答案 6 :(得分:1)
根据“Ruby 2.0.0 by Example”,您必须有默认值:
在Ruby 2.0.0中,关键字参数必须具有默认值,否则必须在最后添加** extra。
答案 7 :(得分:0)
您可以定义命名参数,例如
def test(var1: var1, var2: var2, var3: var3)
puts "#{var1} #{var2} #{var3}"
end
如果你没有传递其中一个参数,那么Ruby会抱怨undefined local variable or method
。
答案 8 :(得分:0)
把它留在这里是因为它对我帮助很大。
假设你有这个:
def foo(thing, to_print)
if to_print
puts thing
end
end
# this works
foo("hi", true)
# hi
# => nil
所以您尝试添加参数名称,如下所示:
foo(thing: "hi", to_print: true)
# foo(thing: "hi", to_print: true)
# ArgumentError: wrong number of arguments (given 1, expected 2)
# from (pry):42:in `foo'
但不幸的是它出错了。
只需在每个参数的末尾添加一个 :
:
def foo2(thing:, to_print:)
if to_print
puts thing
end
end
foo2(thing: "hi", to_print: true)
# hi
# => nil
它有效!