web-dev-qa-db-fra.com

Paramètres nommés dans Ruby 2

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
39
Alan Coromano

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 ".

18
phoet

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.

34
AndyV

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 .

13
Josh Diehl

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"
11
trliner

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.

5
Chris Cox
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
2
aaandre

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.

1

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.

0
Clemens Helm