Je ne comprends pas complètement comment les paramètres nommés dans Ruby 2.0 fonctionnent.
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)
il est traité comme un hachage. Et c'est très drôle car utiliser des paramètres nommés dans Ruby 2.0 I must définir des valeurs par défaut pour eux:
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
ce qui est très similaire au comportement que Ruby avait auparavant avec les valeurs des paramètres par défaut:
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
Je sais pourquoi cela se produit et presque comment cela fonctionne.
Mais je suis juste curieux, must J'utilise des valeurs par défaut pour les paramètres si j'utilise des paramètres nommés?
Et, quelqu'un peut-il me dire alors quelle est la différence entre ces deux?
def test1(var1="default value123")
#.......
end
def test1(var1:"default value123")
#.......
end
Premièrement, le dernier exemple que vous avez publié est trompeur. Je suis totalement en désaccord sur le fait que le comportement est similaire au précédent. Le dernier exemple passe l'argument hachage en tant que premier paramètre facultatif, ce qui est différent!
Si vous ne souhaitez pas avoir de valeur par défaut, vous pouvez simplement utiliser nil
.
Si vous voulez lire un bon article, voir " Arguments de mot-clé Ruby 2 ".
Je pense que la réponse à votre question mise à jour peut être expliquée avec des exemples explicites. Dans l'exemple ci-dessous, vous avez des paramètres facultatifs dans un ordre explicite:
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'
L'approche des paramètres nommés est différente. Il vous permet toujours de fournir des valeurs par défaut, mais il permet à l'appelant de déterminer, le cas échéant, les paramètres à fournir:
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'
S'il est vrai que les deux approches sont similaires lorsqu'elles sont fournies sans paramètres, elles diffèrent lorsque l'utilisateur fournit des paramètres à la méthode. Avec les paramètres nommés, l'appelant peut spécifier quel paramètre est fourni. Plus précisément, le dernier exemple (ne fournissant que l'adresse) n'est pas tout à fait réalisable dans le premier exemple; vous pouvez obtenir des résultats similaires UNIQUEMENT en fournissant les DEUX paramètres à la méthode. Cela rend l'approche des paramètres nommés beaucoup plus flexible.
Je suis d'accord avec vous qu'il est bizarre d'exiger des valeurs par défaut comme prix pour l'utilisation de paramètres nommés, et évidemment les responsables de Ruby sont d'accord avec nous! Ruby 2.1 sera - supprimer l'exigence de valeur par défaut à partir de 2.1.0-preview1 .
Depuis Ruby 2.1. , vous n'avez plus à définir de valeurs par défaut pour les paramètres nommés. Si vous omettez la valeur par défaut d'un paramètre, l'appelant devra la fournir.
def concatenate(val1: 'default', val2:)
"#{val1} #{val2}"
end
concatenate(val2: 'argument')
#=> "default argument"
concatenate(val1: 'change')
#=> ArgumentError: missing keyword: val2
Donné:
def test1(var1="default value123")
var1
end
def test2(var1:"default value123")
var1
end
Ils se comporteront de la même manière lorsqu'ils ne passeront pas d'argument:
test1
#=> "default value123"
test2
#=> "default value123"
Mais ils se comporteront très différemment lorsqu'un argument est passé:
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"
Ceci est présent dans toutes les autres réponses, mais je veux extraire cette essence.
Il existe quatre types de paramètres:
Required Optional
Positional | def PR(a) | def PO(a=1) |
Keyword | def KR(a:) | def KO(a:1) |
Lors de la définition d'une fonction, les arguments de position sont spécifiés avant les arguments de mot-clé et les arguments requis avant les arguments facultatifs.
irb(main):006:0> def argtest(a,b=2,c:,d:4)
irb(main):007:1> p [a,b,c,d]
irb(main):008:1> end
=> :argtest
irb(main):009:0> argtest(1,c: 3)
=> [1, 2, 3, 4]
irb(main):010:0> argtest(1,20,c: 3,d: 40)
=> [1, 20, 3, 40]
edit: l'argument de mot clé requis (sans valeur par défaut) est nouveau depuis Ruby 2.1.0, comme mentionné par d'autres.
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.
Vous pouvez définir la valeur par défaut et le nom du paramètre, puis appeler la méthode comme vous l'appelleriez si vous aviez des paramètres "nommés" basés sur le hachage mais sans avoir besoin de définir des valeurs par défaut dans votre méthode.
Vous en aurez besoin dans votre méthode pour chaque "paramètre nommé" si vous utilisiez un hachage.
b = options_hash[:b] || 2
un péché:
def test(a = 1, options_hash)
b = options_hash[:b] || 2
c = options_hash[:c] || 3
p [a,b,c]
end
Selon " Ruby 2.0.0 par exemple " vous devez avoir des valeurs par défaut:
Dans Ruby 2.0.0, les arguments de mot-clé doivent avoir des valeurs par défaut, sinon ils doivent être capturés par ** extra à la fin.
Vous pouvez définir des paramètres nommés comme
def test(var1: var1, var2: var2, var3: var3)
puts "#{var1} #{var2} #{var3}"
end
Si vous ne passez pas l'un des paramètres, alors Ruby se plaindra d'un undefined local variable or method
.