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

Posted

技术标签:

【中文标题】使用 ruby​​ splat 运算符在哪里合法?【英文标题】:Where is it legal to use ruby splat operator? 【发布时间】:2010-10-21 01:26:04 【问题描述】:

Splats 很酷。它们不仅仅用于爆炸数组,尽管这很有趣。它们还可以转换为 Array 和展平数组(请参阅 http://github.com/mischa/splat/tree/master 了解它们所做的详尽列表。)

看起来无法对 splat 执行其他操作,但在 1.8.6/1.9 中,以下代码会抛出“unexpected tSTAR”:

foo = bar || *zap #=> unexpected tSTAR

而这有效:

foo = *zap || bar #=> works, but of limited value

splat 可以出现在表达式中的什么位置?

【问题讨论】:

【参考方案1】:

“splat 运算符”实际上根本不是运算符,而是 Ruby 语法中定义的标记。通读 Grammar.y 或 BNF 形式* 的 Ruby 语法会告诉您它可以作为最后一个或唯一的参数:

在方法定义中(除了可选的最后一个&foo) 在方法调用中(除了可选的最后一个&foo) 在 as 的 LHS 上赋值,例如:a, b, *cs = [1,2,3,4] 在作业的 RHS 上,例如:a, b, c = 1, 2, *[3,4,5] 在 case 语句的 when 子句中

【讨论】:

这是用于 Ruby 1.8 还是 Ruby 1.9? @ReinHenrichs 在哪里可以找到 Ruby 语法?【参考方案2】:

首先,优先级在这里不是问题,因为foo = bar || (*zap) 的效果并没有更好。一般的经验法则是您不能对 splat 执行其他操作。即使像foo = (*zap) 这样简单的东西也是无效的。这也适用于 1.9。

话虽如此,您希望foo = bar || *zap 做什么,如果它有效,那与foo = bar || zap 不同?即使在像a, b = bar || *zap(也不起作用)这样的情况下,a, b = bar || zap 也完成了我认为相同的事情。

这可能有意义的唯一情况是a, b = foo, bar || *zap。您应该会发现a, b = foo, *(bar || zap) 涵盖了您想要使用它的大多数情况。如果这不包括你的情况,你可能应该问问自己,你真正希望通过编写这样一个丑陋的结构来实现什么。


编辑:

响应您的 cmets,*zap || bar 等同于 *(zap || bar)。这表明 splat 的优先级有多低。它到底有多低?我能给你的最佳答案是“相当低”。

不过,举个有趣的例子,考虑一个方法foo,它接受三个参数:

def foo(a, b, c)
  #important stuff happens here!
end

foo(*bar = [1, 2, 3]) 将在赋值后飞溅并将参数分别设置为 1、2 和 3。将其与 foo((*bar = [1, 2, 3])) 进行比较,后者会抱怨参数数量错误(1 比 3)。

【讨论】:

该示例仅用于说明。多年前我完成了我在生活中想要的一切,现在我只是喜欢探索 Ruby 的深度。不是吗? :) 另外,是否可以更精确?对条中的 splat 执行了哪些附加操作 || *zap 与 *zap ||酒吧? 对不起,我想说的是:*zap || bar 等价于 *(zap || bar)。这意味着 splat 绑定的时间有多晚。到底有多晚?我能给你的最好答案是“很晚了”。举个有趣的例子,考虑一个 foo 方法,它接受三个参数: foo(*c = [1, 2, 3]) 将在赋值后飞溅,并将参数分别设置为 1、2 和 3。 非常感谢 Pesto - 请您将有关后期绑定的内容和您的示例放在答案的顶部,然后我会接受吗?

以上是关于使用 ruby​​ splat 运算符在哪里合法?的主要内容,如果未能解决你的问题,请参考以下文章

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

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

如何将数组传递给接受带有 splat 运算符的属性的方法?

ruby 在案例时使用带阵列的splat

了解范围和数组中的 ruby​​ splat

ruby 使用splat进行方法参数