Подтвердить что ты не робот

В Ruby нет названных параметров?

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

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

meth(1, scope = "meh")

-> "meh"

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

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

4b9b3361

Ответ 1

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

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

Ответ 2

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

  • Вы определяете параметр метода с именем "scope" со значением по умолчанию "scope"
  • Когда вы вызываете метод, вы присваиваете значение "meh" новой локальной переменной с именем "scope" , которая не связана с именем параметра в методе, который вы вызываете.

Ответ 3

Хотя именованные параметры не поддерживаются языком 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.

Ответ 4

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

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

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