a clean way to combine two tuples into a new larger tuple in scala?

混江龙づ霸主 提交于 2019-12-09 04:20:21

问题


Let's say I have the following tuples:

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)

Is there a friendly way to combine them (in two steps if necessary) into a Tuple7? I'm really looking for a general answer for combining tuples of arbitrary size, and realize that there will be limitations due to the capped maximum tuple size. I am specifically looking for a tuple result, not a collection.


回答1:


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)



回答2:


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.



来源:https://stackoverflow.com/questions/9028459/a-clean-way-to-combine-two-tuples-into-a-new-larger-tuple-in-scala

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!