25

在 Python 中,我们有星号(或“*”或“解包”)运算符,它允许我们解包列表,以便在传递位置参数时使用。例如:

range(3, 6)
args = [3, 6]
# invokes range(3, 6)
range(*args)

在这个特定的例子中,它并没有节省太多的输入,因为range只需要两个参数。但是您可以想象,如果 有更多参数range,或者args从输入源读取,从另一个函数返回等,那么这可能会派上用场。

在 Scala 中,我一直无法找到等价物。考虑在 Scala 交互式会话中运行的以下命令:

case class ThreeValues(one: String, two: String, three: String)

//works fine
val x = ThreeValues("1","2","3")

val argList = List("one","two","three")

//also works
val y = ThreeValues(argList(0), argList(1), argList(2))

//doesn't work, obviously
val z = ThreeValues(*argList)

除了中使用的方法之外,还有更简洁的方法val y吗?

4

4 回答 4

38

scala 中没有直接的等价物。您会发现最接近的是 的用法_*,它仅适用于可变参数方法。例如,这里是一个可变参数方法的例子:

def hello( names: String*) {
  println( "Hello " + names.mkString(" and " ) )
}

可以与任意数量的参数一起使用:

scala> hello()
Hello
scala> hello("elwood")
Hello elwood
scala> hello("elwood", "jake")
Hello elwood and jake

现在,如果你有一个字符串列表并想将它们传递给这个方法,解压它的方法是通过_*

scala> val names = List("john", "paul", "george", "ringo")
names: List[String] = List(john, paul, george, ringo)
scala> hello( names: _* )
Hello john and paul and george and ringo    
于 2013-02-22T23:09:05.870 回答
5

你可以使用shapeless来获得 Python 的一些方法,

Welcome to Scala version 2.11.0-20130208-073607-ce32c1af46 (Java HotSpot(TM) 64-Bit Server VM, Java 1.7.0_05).
Type in expressions to have them evaluated.
Type :help for more information.

scala> import shapeless._
import shapeless._

scala> import Traversables._
import Traversables._

scala> case class ThreeValues(one: String, two: String, three: String)
defined class ThreeValues

scala> val argList = List("one","two","three")
argList: List[String] = List(one, two, three)

scala> argList.toHList[String :: String :: String :: HNil].map(_.tupled).map(ThreeValues.tupled)
res0: Option[ThreeValues] = Some(ThreeValues(one,two,three))

正如你所看到的,在 Scala 中,无形的需要更多的仪式。这是因为 shapeless 施加了保证在运行时满足的编译时间约束(与 python 不同,如果args大小错误或包含错误类型的元素,它将在运行时失败)......相反,你被迫指定键入您希望 List 具有的类型(在这种情况下恰好是三个Strings),并准备处理不满足该期望的情况(因为结果明确是Optionof ThreeValues)。

于 2013-02-23T02:22:21.050 回答
4

函数也有类似的东西:tupled它将一个接受 n 个参数的函数转换为一个接受一个 n 元组类型参数的函数。

有关更多信息,请参阅此问题:scala tuple unpacking

这样的数组方法没有多大意义,因为它只适用于具有多个相同类型参数的函数。

于 2013-02-22T23:07:25.087 回答
3

另一种解压列表的方法:

val a :: b :: c :: _ = argList
val z = ThreeValues(a, b, c)
于 2020-12-23T18:50:24.417 回答