Нет именованных параметров в Ruby? - PullRequest
32 голосов
/ 08 марта 2012

Это так просто, что я не могу поверить, что это поймало меня.

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

meth(1, scope = "meh")

-> "meh"

Я склонен использовать хэши для параметров аргументов только потому, что это было именно так, как это делало стадо - и это довольно чисто. Я думал, что это был стандарт. Сегодня, после 3 часов поиска ошибок, я обнаружил ошибку в этом драгоценном камне, который, как мне кажется, использует, что предполагает, что именованные параметры будут соблюдены. Это не так.

Итак, мой вопрос таков: официально названный параметр не соблюдается в Ruby (1.9.3), или это побочный эффект чего-то, чего я упускаю? Если нет, то почему бы и нет?

Ответы [ 4 ]

38 голосов
/ 08 марта 2012

Что на самом деле происходит:

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

Нет поддержки * для именованных параметров (см. Ниже обновление 2.0). То, что вы видите, является просто результатом присвоения "meh" для scope, передаваемого как значение options в meth. Значение этого назначения, конечно, составляет "meh".

Есть несколько способов сделать это:

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"

И так далее. Однако все они обходные пути из-за отсутствия именованных параметров.


Изменить (15 февраля 2013 г.):

* Ну, по крайней мере до следующего выпуска Ruby 2.0 , который поддерживает аргументы ключевых слов! На момент написания статьи он находится на выпуске кандидата 2, последнего перед официальным релизом. Хотя для работы с 1.8.7, 1.9.3 и т. Д. Вам необходимо знать описанные выше методы, у тех, кто может работать с более новыми версиями, теперь есть следующая опция:

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

meth 1, scope: "meh"
# => "options"
5 голосов
/ 08 марта 2012

Я думаю, что здесь происходят 2 вещи:

  1. Вы определяете параметр для метода с именем scope с значением по умолчанию «scope»
  2. Когда вы вызываетеметод, вы присваиваете значение "meh" новой локальной переменной с именем "scope", которая не связана с именем параметра вызываемого вами метода.
3 голосов
/ 08 марта 2012

Хотя именованные параметры не поддерживаются языком Ruby, вы можете имитировать их, передавая аргументы вашей функции через хеш. Например:

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

  puts options
end

Что можно использовать следующим образом:

meth(1, scope: "meh")

Ваш существующий код просто назначает переменную, а затем передает эту переменную в вашу функцию. Для получения дополнительной информации см .: http://deepfall.blogspot.com/2008/08/named-parameters-in-ruby.html.

0 голосов
/ 08 марта 2012

Ruby не имеет именованных параметров.

Пример определения метода имеет параметры со значениями по умолчанию.

Пример сайта вызова присваивает значение локальной переменной вызывающей области с именем scope , а затем передает ее значение (meh) параметру options .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...