Подтвердить что ты не робот

Чистый способ объединить два кортежа в новый большой кортеж в scala?

Скажем, у меня есть следующие кортежи:

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)

Есть ли дружеский способ объединить их (в два шага, если необходимо) в Tuple7? Я действительно ищу общий ответ для комбинирования кортежей произвольного размера и понимаю, что будут ограничения из-за ограниченного максимального размера кортежа. Я специально искал результат кортежа, а не коллекцию.

4b9b3361

Ответ 1

Shapeless требует зависимых типов методов (-Ydependent-method-types), и мне жаль, что для 2.9.1 не было загружаемого бинарного файла, чтобы я мог просто попробуйте, но это действительно кажется элегантным. На основе этот unit test он применим к вашему случаю следующим образом:

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

Хотя Miles указывает, что нет гарантии поддержки, на самом деле он имеет модульные тесты, а источник находится на github с лицензией с открытым исходным кодом, поэтому, по крайней мере, это не просто эксперимент в блоге.

Изменить: работает как рекламируется - потребовалось некоторое время для компиляции, и мне пришлось добавить -Xss1m в 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

Вам действительно нужно использовать коллекции здесь, особенно если все элементы одного типа. Вы можете комбинировать кортежи в List без особых трудностей:

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

Используя ваш пример:

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

Попытка превратить это обратно в кортежи не будет работать, потому что ваш метод преобразования (например, с сопоставлением с образцом) не сможет вернуть конкретный тип кортежа (какой тип возвращаемого метода?) и информация о типе каждого элемента была потеряна.