web-dev-qa-db-ja.com

Scala Python list unpack(a.k.a。 "*")演算子に相当するものはありますか?

Pythonには、スター(または「*」または「アンパック」)演算子があります。これにより、位置引数を渡す際に便利に使用できるようにリストをアンパックできます。例えば:

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

この特定の例では、rangeは2つの引数しかとらないため、入力をあまり節約できません。しかし、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で使用されている方法以外に、これを行うためのより簡潔な方法はありますか?

22
Jeff Evans

関数にも同様のことがあります。tupled n個のパラメーターを受け取る関数を、タイプn-Tupleの1つの引数を受け取る関数に変換します。

詳細については、この質問を参照してください: scala Tuple unpacking

このような配列のメソッドは、同じタイプの複数の引数を持つ関数でのみ機能するため、あまり意味がありません。

4
Jens Schauder

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    
27

Python using shapeless

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 with shapelessでは、もう少しセレモニーが必要です。これは、shapelessがコンパイル時の制約を課し、実行時に満たされることが保証されているためです(Pythonとは異なり、 argsが間違ったサイズであるか、間違ったタイプの要素が含まれている場合のランタイム)...代わりに、リストに期待するタイプ(この場合は正確に3つのStrings)を指定する必要があります。 )そして、その期待が満たされない場合を処理する準備をします(結果は明示的にOptionThreeValuesであるため)。

4
Miles Sabin