2013-05-01 7 views
4

Je voudrais créer une fonction qui a des arguments en option avec des valeurs par défautArguments de valeur par défaut dans Ruby

def my_function(a = nil, b=nil, c=500) 

end 

et appeler la fonction avec les arguments que je voudrais préciser que

my_function(b=100) 

Comment l'accomplir dans Ruby 1.9.2?

Répondre

6

Vous ne pouvez pas faire cela (ou quelque chose de similaire) dans Ruby < 2.0. Le mieux que vous puissiez faire est:

def my_function(h = {}) 
    h[:c] ||= 500 
    # Use h[:a], h[:b], h[:c] 
    ... 
end 

my_function(b: 100) 
+2

-1. C'est faux. Vous pouvez avoir autant d'arguments optionnels que vous le souhaitez, et ils n'ont pas besoin d'être en dernier. 'def foo (mand1, mand2, opt1 =: opt1, opt2 =: opt2, * splat, mand3, mand4, & block) p local_variables.map {| v | "# {v} = # {eval (v.to_s)}"} end' est parfaitement bien. –

+1

@ JörgWMittag Droite. J'avais tort à ce sujet. Je vais retirer cette partie. – sawa

+0

@ JörgWMittag Je pense qu'une ancienne version de Ruby nécessitait que les arguments ayant les valeurs par défaut soient, si ce n'est derniers, au moins après tous les arguments "ordinaires". –

8

Vous essayez donc d'implémenter des arguments de mots-clés? Ceci est supposé être une nouvelle fonctionnalité dans Ruby 2.0, mais vous pouvez essayer de l'imiter dans 1.9.x avec un hachage d'arguments à la place. Here's a post qui explique comment vous pouvez accomplir cela, ce qui donne l'exemple de code suivant:

def foo(options = {}) 
    options = {bar: 'bar'}.merge(options) 
    puts "#{options[:bar]} #{options[:buz]}" 
end 

foo(buz: 'buz') # => 'bar buz' 
+9

Ne créez pas de réponses qui contiennent uniquement un lien vers une réponse. * QUAND * ce lien se casse, votre réponse sera-t-elle utile? Au lieu de cela, résumez la partie pertinente de cette réponse. –

+1

Le lien est cassé –

22

Les arguments sont liés à des paramètres comme ceci:

  1. Tant qu'il y aura des paramètres obligatoires non liés au début de la liste de paramètres, lier les arguments de gauche à droite
  2. Tant qu'il existe des paramètres obligatoires non liés à la fin de la liste de paramètres, affectez les arguments de droite à gauche
  3. Les arguments restants sont liés à opti paramètres Onal gauche à droite-
  4. Les arguments restants sont collectés dans un tableau et lié à l'argument floc
  5. Un bloc est enveloppé dans un Proc et lié à l'argument de bloc
  6. S'il y a des paramètres non liés ou arguments restants, raise un ArgumentError

Voici un exemple:

def foo(mand1, mand2, opt1=:opt1, opt2=:opt2, *splat, mand3, mand4, &block) 
    p local_variables.map {|v| "#{v} = #{eval(v.to_s)}" } 
end 

foo 1, 2, 3 
# ArgumentError: wrong number of arguments (3 for 4+) 

foo 1, 2, 3, 4 
# mand1 = 1 
# mand2 = 2 
# opt1 = opt1 
# opt2 = opt2 
# splat = [] 
# mand3 = 3 
# mand4 = 4 
# block = 

foo 1, 2, 3, 4, 5 
# mand1 = 1 
# mand2 = 2 
# opt1 = 3 
# opt2 = opt2 
# splat = [] 
# mand3 = 4 
# mand4 = 5 
# block = 

foo 1, 2, 3, 4, 5, 6 
# mand1 = 1 
# mand2 = 2 
# opt1 = 3 
# opt2 = 4 
# splat = [] 
# mand3 = 5 
# mand4 = 6 
# block = 

foo 1, 2, 3, 4, 5, 6, 7 
# mand1 = 1 
# mand2 = 2 
# opt1 = 3 
# opt2 = 4 
# splat = [5] 
# mand3 = 6 
# mand4 = 7 
# block = 

foo 1, 2, 3, 4, 5, 6, 7, 8 do end 
# mand1 = 1 
# mand2 = 2 
# opt1 = 3 
# opt2 = 4 
# splat = [5, 6] 
# mand3 = 7 
# mand4 = 8 
# block = #<Proc:[email protected](pry):42> 

donc, comme vous pouvez le voir à la fois à partir de l'étape 3 ci-dessus et de l'exemple, vous ne pouvez pas le faire, car les paramètres facultatifs sont liés de gauche à droite, mais vous souhaitez spécifier l'argument du milieu. Notez que cela a des implications sur la conception de l'API: vous devez concevoir vos listes de paramètres de manière à ce que les paramètres optionnels les plus "instables", c'est-à-dire ceux que l'utilisateur souhaite probablement se procurer, soient les plus à gauche .

Ruby 2.0 a maintenant des arguments mot-clé, ce qui est exactement ce que vous cherchez:

def foo(m1, m2, o1=:o1, o2=:o2, *s, m3, m4, key1: :key1, key2: :key2, **keys, &b) 
    puts local_variables.map {|v| "#{v} = #{eval(v.to_s)}" } 
end 

foo 1, 2, 3 
# ArgumentError: wrong number of arguments (3 for 4+) 

foo 1, 2, 3, 4 
# m1 = 1 
# m2 = 2 
# o1 = o1 
# o2 = o2 
# s = [] 
# m3 = 3 
# m4 = 4 
# key1 = key1 
# key2 = key2 
# b = 
# keys = {} 

foo 1, 2, 3, 4, 5 
# m1 = 1 
# m2 = 2 
# o1 = 3 
# o2 = o2 
# s = [] 
# m3 = 4 
# m4 = 5 
# key1 = key1 
# key2 = key2 
# b = 
# keys = {} 

foo 1, 2, 3, 4, 5, 6 
# m1 = 1 
# m2 = 2 
# o1 = 3 
# o2 = 4 
# s = [] 
# m3 = 5 
# m4 = 6 
# key1 = key1 
# key2 = key2 
# b = 
# keys = {} 

foo 1, 2, 3, 4, 5, 6, 7 
# m1 = 1 
# m2 = 2 
# o1 = 3 
# o2 = 4 
# s = [5] 
# m3 = 6 
# m4 = 7 
# key1 = key1 
# key2 = key2 
# b = 
# keys = {} 

foo 1, 2, 3, 4, 5, 6, 7, 8 
# m1 = 1 
# m2 = 2 
# o1 = 3 
# o2 = 4 
# s = [5, 6] 
# m3 = 7 
# m4 = 8 
# key1 = key1 
# key2 = key2 
# b = 
# keys = {} 

foo 1, 2, 3, 4, 5, 6, 7, 8, key1: 9 
# m1 = 1 
# m2 = 2 
# o1 = 3 
# o2 = 4 
# s = [5, 6] 
# m3 = 7 
# m4 = 8 
# key1 = 9 
# key2 = key2 
# b = 
# keys = {} 

foo 1, 2, 3, 4, 5, 6, 7, 8, key1: 9, key2: 10 
# m1 = 1 
# m2 = 2 
# o1 = 3 
# o2 = 4 
# s = [5, 6] 
# m3 = 7 
# m4 = 8 
# key1 = 9 
# key2 = 10 
# b = 
# keys = {} 

foo 1, 2, 3, 4, 5, 6, 7, 8, key1: 9, key2: 10, key3: 11 
# m1 = 1 
# m2 = 2 
# o1 = 3 
# o2 = 4 
# s = [5, 6] 
# m3 = 7 
# m4 = 8 
# key1 = 9 
# key2 = 10 
# b = 
# keys = {:key3=>11} 

foo 1, 2, 3, 4, 5, 6, 7, 8, key1: 9, key2: 10, key3: 11, key4: 12 do end 
# m1 = 1 
# m2 = 2 
# o1 = 3 
# o2 = 4 
# s = [5, 6] 
# m3 = 7 
# m4 = 8 
# key1 = 9 
# key2 = 10 
# b = #<Proc:[email protected](pry):77> 
# keys = {:key3=>11, key4=>12} 
+0

Merci beaucoup, Jorg. Très informatif – AdamNYC

Questions connexes