Ruby 中没有命名参数?

Posted

技术标签:

【中文标题】Ruby 中没有命名参数?【英文标题】:No named parameters in Ruby? 【发布时间】:2012-03-25 15:09:13 【问题描述】:

这太简单了,我简直不敢相信它抓住了我。

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

meth(1, scope = "meh")

-> "meh"

我倾向于使用散列作为参数选项,只是因为它是牛群的做法——而且它非常干净。我以为这是标准。今天,经过大约 3 个小时的 bug 搜寻,我发现了一个错误,我碰巧使用了这个 gem,assumes 命名参数将被兑现。他们不是。

所以,我的问题是:在 Ruby (1.9.3) 中是否正式不支持命名参数,或者这是我缺少的东西的副作用?如果不是,为什么不呢?

【问题讨论】:

关于 Ruby 2.0 中的命名参数的讨论:bugs.ruby-lang.org/issues/5474 Ruby 2.0.0 is released,不是你can use named parameters。 相关:***.com/questions/8021628/…“命名参数的工作原理” ruby keyword arguments of method的可能重复 【参考方案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 的结果,作为meth 中的options 值传递。当然,该赋值的值是"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"

等等。不过,由于缺少命名参数,它们都是解决方法。


编辑(2013 年 2 月 15 日):

* 好吧,at least until the upcoming 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"

【讨论】:

是的,这就是我所假设的。我从来没有想过它,因为我从来没有在 Ruby 中真正使用过 命名参数。我一直使用哈希。然后,当我在这个编码良好的 gem 中看到它时,我感到很惊讶。 @JohnMetta 是的,这听起来像是开发人员的心理失误。让他或她知道可能是个好主意,但我不能责怪开发者的一厢情愿。 ;) 我确实这样做了。 Github 问题。我正在考虑重建它并提交一个拉取请求,但我需要先对我的项目进行动议,所以现在只需要解决它。【参考方案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 参数。

【讨论】:

以上是关于Ruby 中没有命名参数?的主要内容,如果未能解决你的问题,请参考以下文章

为啥不能在 Ruby 3 中结合 `...` 和命名参数?

何时在 Ruby 中使用关键字参数,也就是命名参数

命名参数作为 Ruby 中的局部变量

如何在子类中添加命名参数或在 Ruby 2.2 中更改它们的默认值?

ruby 重命名参数

命名这个 python/ruby 语言结构(使用数组值来满足函数参数)