32 votes

Pas de paramètres nommés en Ruby ?

C'est tellement simple que je n'arrive pas à croire que je l'ai compris.

def meth(id, options = "options", scope = "scope")
  puts options
end

meth(1, scope = "meh")

-> "meh"

J'ai tendance à utiliser des hachages pour les options d'argumentation, simplement parce que c'est ainsi que le troupeau procédait - et c'est assez propre. Je pensais que c'était la norme. Aujourd'hui, après environ 3 heures de chasse aux bogues, j'ai remonté une erreur jusqu'à cette gemme que j'utilise qui suppose les paramètres nommés seront respectés. Ils ne le sont pas.

Ma question est donc la suivante : Les paramètres nommés sont-ils officiellement ignorés en Ruby (1.9.3), ou s'agit-il d'un effet secondaire de quelque chose qui m'échappe ? Si ce n'est pas le cas, pourquoi ?

38voto

brymck Points 5349

Ce qui se passe en réalité :

# Assign a value of "meh" to scope, which is OUTSIDE meth and equivalent to
#   scope = "meth"
#   meth(1, scope)
meth(1, scope = "meh")

# Ruby takes the return value of assignment to scope, which is "meh"
# If you were to run `puts scope` at this point you would get "meh"
meth(1, "meh")

# id = 1, options = "meh", scope = "scope"
puts options

# => "meh"

Il n'y a pas de support* pour les paramètres nommés (voir ci-dessous pour la mise à jour 2.0). Ce que vous voyez est juste le résultat de l'assignation de "meh" a scope étant transmis en tant que options valeur en meth . La valeur de cette affectation est bien sûr "meh" .

Il y a plusieurs façons de procéder :

def meth(id, opts = {})
  # Method 1
  options = opts[:options] || "options"
  scope   = opts[:scope]   || "scope"

  # Method 2
  opts = { :options => "options", :scope => "scope" }.merge(opts)

  # Method 3, for setting instance variables
  opts.each do |key, value|
    instance_variable_set "@#{key}", value
    # or, if you have setter methods
    send "#{key}=", value
  end
  @options ||= "options"
  @scope   ||= "scope"
end

# Then you can call it with either of these:
meth 1, :scope => "meh"
meth 1, scope: "meh"

Et ainsi de suite. Il s'agit de solutions de contournement pour pallier l'absence de paramètres nommés.


Edit (15 février 2013) :

* Bien, au moins jusqu'à la prochaine version de Ruby 2.0 qui prend en charge les arguments liés aux mots clés ! A l'heure où j'écris ces lignes, il en est à la release candidate 2, la dernière avant la sortie officielle. Bien que vous deviez connaître les méthodes ci-dessus pour travailler avec 1.8.7, 1.9.3, etc., ceux qui peuvent travailler avec des versions plus récentes ont maintenant l'option suivante :

def meth(id, options: "options", scope: "scope")
  puts options
end

meth 1, scope: "meh"
# => "options"

5voto

Jon M Points 6455

Je pense que deux choses se produisent ici :

  1. Vous définissez un paramètre sur la méthode nommé "scope" avec une valeur par défaut de "scope"
  2. Lorsque vous appelez la méthode, vous affectez la valeur "meh" à un nouveau fichier local variable nommée "scope", qui n'a aucun rapport avec le nom du paramètre de la méthode que vous appelez.

3voto

Kevin Sylvestre Points 15551

Bien que les paramètres nommés ne soient pas supportés par le langage Ruby, vous pouvez les simuler en passant vos arguments de fonction à travers un hachage. Par exemple :

def meth(id, parameters = {})
  options = parameters["options"] || "options"
  scope = parameters["scope"] || "scope"

  puts options
end

qui peut être utilisé comme suit :

meth(1, scope: "meh")

Votre code existant attribue simplement une variable, puis transmet cette variable à votre fonction. Pour plus d'informations, voir http://deepfall.blogspot.com/2008/08/named-parameters-in-ruby.html .

0voto

DigitalRoss Points 80400

Ruby n'a pas de paramètres nommés.

L'exemple de définition de méthode comporte des paramètres avec des valeurs par défaut.

L'exemple du site d'appel attribue une valeur à une variable locale du champ d'application de l'appelant nommée champ d'application et transmet sa valeur (sans intérêt) à la options paramètre.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X