当 Row 接受可变参数时,为啥 Scala 编译器会失败并显示“此处不允许 ': _*' 注释”?
Posted
技术标签:
【中文标题】当 Row 接受可变参数时,为啥 Scala 编译器会失败并显示“此处不允许 \': _*\' 注释”?【英文标题】:Why does Scala compiler fail with "no ': _*' annotation allowed here" when Row does accept varargs?当 Row 接受可变参数时,为什么 Scala 编译器会失败并显示“此处不允许 ': _*' 注释”? 【发布时间】:2018-09-03 15:34:03 【问题描述】:我想创建一个带有多个参数的Row
,但不知道它们的编号。我在 Scala 中写了这样的东西:
def customRow(balance: Int,
globalGrade: Int,
indicators: Double*): Row =
Row(
balance,
globalGrade,
indicators:_*
)
在Spark GitHub 上,考虑到apply
方法,Row
对象似乎接受:_*
表示法:
def apply(values: Any*): Row = new GenericRow(values.toArray)
但在编译时,这似乎是不允许的:
Error:(212, 19) no ': _*' annotation allowed here
(such annotations are only allowed in arguments to *-parameters)
indicators:_*
我错过了什么?
【问题讨论】:
【参考方案1】:这个最小的例子可以更好地解释为什么你想做的事情是不允许的:
def f(a: Int, b: Int, c: Int, rest: Int*) = a + b + c + rest.sum
val ns = List(99, 88, 77)
f(11, 22, 33, 44, ns:_*) // Illegal
f(11, 22, 33, ns:_*) // Legal
f(11, 22, ns:_*) // Illegal
基本上,您只能使用:_*
语法将序列作为可变参数rest
直接传递,但这是全有或全无。序列的项目不会在简单参数和可变参数之间共享,可变参数不能同时从简单参数和提供的序列中收集值。
在您的情况下,您尝试调用Row
,就好像它有两个简单的参数,然后是一个可变参数,但事实并非如此。当您自己创建序列时,您正在使其正确地适合签名。
请注意,在动态类型的编程语言中,这通常不是问题。例如,在 Python 中:
>>> def f(a, b, c, *rest):
return a + b + c + sum(rest)
>>> ns = [99, 88, 77]
>>> f(11, 22, 33, 44, *ns)
374
>>> f(11, 22, 33, *ns)
330
>>> f(11, 22, *ns)
297
【讨论】:
【参考方案2】:通过添加中间 Seq 解决它:
def customRow(balance: Int,
globalGrade: Int,
indicators: Double*): Row =
val args = Seq(
balance,
globalGrade
) ++ indicators
Row(
args:_*
)
但是,我仍然不知道它为什么会起作用。
【讨论】:
以上是关于当 Row 接受可变参数时,为啥 Scala 编译器会失败并显示“此处不允许 ': _*' 注释”?的主要内容,如果未能解决你的问题,请参考以下文章