使用 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 运算符吗?