2つのタプルをScalaで新しい大規模なタプルに組み合わせるためのきれいな方法は?

StackOverflow https://stackoverflow.com/questions/9028459

  •  14-11-2019
  •  | 
  •  

質問

次のタプルを持っているとしましょう。

scala> val t1 = Tuple2("abcd", "efg")
t1: (java.lang.String, java.lang.String) = (abcd,efg)

scala> val t2 = Tuple2(1234, "lmnop")
t2: (Int, java.lang.String) = (1234,lmnop)

scala> val t3 = Tuple3("qrs", "tuv", "wxyz")
t3: (java.lang.String, java.lang.String, java.lang.String) = (qrs,tuv,wxyz)
.

それらを(必要に応じて2ステップで)Tuple7に組み合わせるための友好的な方法はありますか?私は任意のサイズのタプルを組み合わせるための一般的な答えを探していて、キャップされた最大タプルサイズのために制限があることを認識しています。私はコレクションではなくタプル結果を特に探しています。

役に立ちましたか?

解決

Shapeless requires dependent method types (-Ydependent-method-types) and I wish there was a downloadable binary for 2.9.1 so that I can simply try it out but it's really seems elegant. Based on this unit test it would apply to your case like this:

import shapeless.Tuples._
import shapeless.HList._
val t7 = (t1.hlisted ::: t2.hlisted ::: t3.hlisted).tupled

Although Miles indicates there is not guarantee of support, it actually has unit tests and the source is on github with an open source license so at least it's not just an experiment in a blog post.

Edit: works as advertized - took some time to compile and I had to add -Xss1m to sbt:

$ scala -Ydependent-method-types -cp target/scala-2.9.1/shapeless_2.9.1-1.1.0.jar
Welcome to Scala version 2.9.1.final (Java HotSpot(TM) Client VM, Java 1.7.0).
Type in expressions to have them evaluated.
Type :help for more information.

scala> import shapeless.Tuples._
import shapeless.Tuples._

scala> import shapeless.HList._
import shapeless.HList._

scala> val t1 = Tuple2("abcd", "efg")
t1: (java.lang.String, java.lang.String) = (abcd,efg)

scala> val t2 = Tuple2(1234, "lmnop")
t2: (Int, java.lang.String) = (1234,lmnop)

scala> val t3 = Tuple3("qrs", "tuv", "wxyz")
t3: (java.lang.String, java.lang.String, java.lang.String) = (qrs,tuv,wxyz)

scala> (t1.hlisted ::: t2.hlisted ::: t3.hlisted).tupled
res0: (java.lang.String, java.lang.String, Int, java.lang.String, java.lang.String,
java.lang.String, java.lang.String) = (abcd,efg,1234,lmnop,qrs,tuv,wxyz)

他のヒント

You really need to be using collections here, especially if all elements are the same type. You can combine tuples into a List without much difficulty:

def combine(xss: Product*) = xss.toList.flatten(_.productIterator)

Using your example:

scala> combine(t1, t2, t3)
res1: List[Any] = List(abcd, efg, hijk, lmnop, qrs, tuv, wxyz)

Trying to turn this back into tuples isn't going to work because your conversion method (e.g. with pattern matching) won't be able to return the specific tuple type (what's the return type of the method?), and the type information of each element has been lost.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top