如何在 Ruby 中为 splat 参数设置默认值

Posted

技术标签:

【中文标题】如何在 Ruby 中为 splat 参数设置默认值【英文标题】:How to set a default value for a splat argument in Ruby 【发布时间】:2013-03-25 16:49:18 【问题描述】:

为 splat 参数设置默认值会出错:

1.9.3-p374 :001 > def a b, *c = nil
1.9.3-p374 :002?>   end
SyntaxError: (irb):1: syntax error, unexpected '=', expecting ';' or '\n'
def a b, *c = nil
             ^
    from /Users/me/.rvm/rubies/ruby-1.9.3-p374/bin/irb:16:in `<main>'

我尝试过的一些变体也不起作用:

1.9.3-p374 :003 > def a b, *c = []
1.9.3-p374 :005 > def a b, (*c) = nil
1.9.3-p374 :007 > def a b, (*c = [])
1.9.3-p374 :009 > def a b, (*c = [1,2,3])
1.9.3-p374 :011 > def a b, *c = [1,2,3]

我在这里没有看到不确定性问题,所以看起来应该是可能的。

相关:Why non-explicit splat param plus default param is wrong syntax for method definition in Ruby 1.9?

【问题讨论】:

Splat 参数默认为空数组 是的,但是默认参数呢? 您还没有接受答案有什么原因吗? @vlasits 我希望有人能解决为什么 Ruby 不允许以通常的方式为 splats 设置默认参数的技术原因。我确实读过你所说的关于这是一个设计决策的内容。 【参考方案1】:

这很方便:

def initialize(*response_names)
  @response_names = response_names.presence || %w(default values)
end

【讨论】:

【参考方案2】:

您尝试的用法违反了 splat 用法的约定。 Splats 应该(至少在 Ruby 中)占用所有 extra(0、1 或更多)值。

如果您知道希望方法参数列表中的第二个值具有默认值,则可以将其从 splat 中取出并在 splat 之前列出,并使用如下默认值:

def a b, c=nil, *d 
  # rest of code omitted
end

编辑: 为了回答你为什么它不能完全清楚地工作的问题。这是语言设计者的设计决定。 Matz 从未打算让 splat 运算符使用默认值。这对我来说似乎很明智,因为它旨在用于捕获不确定数量的变量,并且因为我描述的方法比您描述的可能性更清楚,并且因为您的示例解决的所有问题都可以通过其他方式解决。

【讨论】:

+1 这是解决此问题的正确方法。如果c 很特别,请将其提升为自己的参数条目,并且不要玩试图从 splatted 变量中提取它的游戏。【参考方案3】:

知道默认 splat 返回一个空数组,您可以在方法本身中设置默认值。

def test(a, *b)
  b = "default b" if b == [] # edited as per Tin Man's recommendation
  puts [a, b].inspect
end

test("Test", 1, 2)
# => ["Test", [1, 2]]
test("Test")
# => ["Test", "default b"]

在 Rails 中,您可以检查 b.present?,因为空数组被视为空白。希望对您有所帮助。

【讨论】:

b == [] and b = "default b" 不推荐用于 Ruby 风格。使用b = "default b" if b == [] 谢谢,我采纳了你的建议。这背后有技术原因吗? 这是一个可读性和维护问题。使用布尔值加入条件测试和赋值是非常 C/Perl 的构造;它简洁,几乎是神秘的,没有获得明显的速度,如果有的话。当用 C 或 Perl 编写时,几乎可以像男子气概那样编写,但 Ruby 的方式是为了提高可读性而提供一些简洁性。此外,如果您使用and,然后添加额外的测试或作业,优先顺序可能会咬住您,这很难追踪。使用&amp;&amp; 可以多次避免优先级问题,但不会增加可读性。 非常感谢@theTinMan 的详细说明!【参考方案4】:

一个 splat 参数默认为一个空数组,你不必做任何特别的事情。

def a(b, *c)
  c
end

a("foo")
#=> []

【讨论】:

是的,但是除了 nil 之外的默认参数呢? 查看我的回答,了解当您希望 c 具有默认值时该怎么做

以上是关于如何在 Ruby 中为 splat 参数设置默认值的主要内容,如果未能解决你的问题,请参考以下文章

ruby 使用splat进行方法参数

Ruby 中的关键字参数解包(splat)

Haskell 有像 Python 和 Ruby 这样的 splat 运算符吗?

Double-splat 运算符破坏性地修改了哈希——这是一个 Ruby 错误吗?

Ruby,Splat 的源代码?

使用 ruby​​ splat 运算符在哪里合法?