是否有一个Scala等效的Python列表解压缩(a.k.a。“*”)运算符?

时间:2013-02-22 22:54:08

标签: python scala argument-passing

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

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 个答案:

答案 0 :(得分:25)

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

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    

答案 1 :(得分:4)

函数有类似的东西:tupled它将一个带n个参数的函数转换为一个函数,该函数接受一个类型为n-tuple的参数。

有关详细信息,请参阅此问题:scala tuple unpacking

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

答案 2 :(得分:4)

您可以使用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需要更多的仪式,没有形状。这是因为无形会强制编译时限制,这些约束保证在运行时得到满足(与python不同,如果args的大小错误或者包含错误类型的元素,它将在运行时失败)...而不是你'重新强制指定您希望List具有的类型(在这种情况下恰好是三个Strings)并准备好处理不满足该期望的情况(因为结果显式为Option ThreeValues)。

答案 3 :(得分:2)

另一种解包列表的方法:

val a :: b :: c :: _ = argList
val z = ThreeValues(a, b, c)