(たとえば) 3 つの要素を持つリストをサイズ 3 のタプルに変換するにはどうすればよいですか?
たとえば、私が持っていてval x = List(1, 2, 3)
、これを に変換したいとしましょう(1, 2, 3)
。これどうやってするの?
タイプセーフな方法でこれを行うことはできません。なんで?一般に、実行時までリストの長さを知ることができないためです。ただし、タプルの「長さ」はその型でエンコードする必要があるため、コンパイル時に認識されます。たとえば、(1,'a',true)
のタイプ(Int, Char, Boolean)
は で、これは の砂糖ですTuple3[Int, Char, Boolean]
。タプルにこの制限がある理由は、同種でない型を処理できる必要があるためです。
shapelessを使用した例:
import shapeless._
import syntax.std.traversable._
val x = List(1, 2, 3)
val xHList = x.toHList[Int::Int::Int::HNil]
val t = xHList.get.tupled
toHList
注: コンパイラは、型情報をメソッドに渡す必要がある理由である HList のリストを変換するために、いくつかの型情報を必要とします。
シンプルであり、任意の長さのリストではありませんが、タイプセーフであり、ほとんどの場合の答えです:
val list = List('a','b')
val tuple = list(0) -> list(1)
val list = List('a','b','c')
val tuple = (list(0), list(1), list(2))
リストに名前を付けたり、繰り返したりしたくない場合の別の可能性 (誰かが Seq/head 部分を回避する方法を示してくれることを願っています):
val tuple = Seq(List('a','b')).map(tup => tup(0) -> tup(1)).head
val tuple = Seq(List('a','b','c')).map(tup => (tup(0), tup(1), tup(2))).head
タイプセーフな方法でこれを行うことはできません。Scala では、リストは何らかの型の要素の任意の長さのシーケンスです。型システムが知る限り、x
任意の長さのリストになる可能性があります。
対照的に、タプルのアリティはコンパイル時に認識されている必要があります。x
タプル型への割り当てを許可することは、型システムの安全性の保証に違反します。
実際、技術的な理由から、Scala のタプルは 22 要素に制限されていましたが、2.11 ではその制限はなくなりました ケース クラスの制限は 2.11 で解除されましたhttps://github.com/scala/scala/pull/2305
最大 22 個の要素のリストを変換し、より大きなリストに対して例外をスローする関数を手動でコーディングすることは可能です。今後の機能である Scala のテンプレート サポートにより、これがより簡潔になります。しかし、これは醜いハックです。
あなたはこれを行うことができます
リストを反復処理し、各要素を 1 つずつ適用します。
val xs: Seq[Any] = List(1:Int, 2.0:Double, "3":String)
val t: (Int,Double,String) = xs.foldLeft((Tuple3[Int,Double,String] _).curried:Any)({
case (f,x) => f.asInstanceOf[Any=>Any](x)
}).asInstanceOf[(Int,Double,String)]
タイプがある限り:
val x: List[Int] = List(1, 2, 3)
def doSomething(a:Int *)
doSomething(x:_*)