Векторизация функции Scala с несколькими возвращаемыми значениями

Каков самый элегантный способ векторизации функции scala, которая возвращает несколько значений?

Например, предположим, что у меня есть функция:

def Foobar(foo: Int, bar: Int): (Int, Int) = (foo, bar)

Если бы он возвращал одно значение, я бы сделал что-то вроде этого:

val a = Array(1, 2, 3)
val b = Array(4, 5, 6)
val c = (a,b).zipped.map(foobar)

Но поскольку он возвращает кортеж, я получаю Array[(Int,Int)], тогда как я бы предпочел (Array[Int], Array[Int]). Каков правильный способ сделать что-то подобное? Есть ли какие-нибудь умные шаблоны для обобщения этого до чего-то вроде этого:

val c = vectorized(foobar,a,b)

Любые идеи будут высоко оценены. Спасибо!


person supyo    schedule 05.12.2012    source источник


Ответы (2)


Вы можете разархивировать его (очевидно, это операция, обратная архивированию):

val c = foobar(a,b).unzip
//res2: (s.c.m.IndexedSeq[Int], s.c.m.IndexedSeq[Int]) = (ArrayBuffer(1, 2, 3),ArrayBuffer(4, 5, 6))

Но вы получите IndexedSeqs, а не массивы.

person om-nom-nom    schedule 05.12.2012

Ну, вы, конечно, можете написать функцию vectorized, если хотите, хотя вам нужны разные функции для каждой входной и выходной арности. Вот версия 2.10 (2.9 будет использовать Manifest вместо ClassTag) для двух входов и двух выходов:

import reflect.ClassTag
def vectorized[A, B, C: ClassTag, D: ClassTag](
  f: (A,B) => (C,D), a: Array[A], b: Array[B]
): (Array[C], Array[D]) = {
  val c = Array.newBuilder[C]
  val d = Array.newBuilder[D]
  for (i <- 0 until math.min(a.length, b.length)) {
    val x = f(a(i), b(i))
    c += x._1
    d += x._2
  }
  (c.result, d.result)
}
person Rex Kerr    schedule 05.12.2012
comment
@ziggystar - Зачем? Shapeless рассчитан на максимальную мощность системы типа, а не на производительность! Вероятно, вы могли бы использовать debox. - person Rex Kerr; 05.12.2012
comment
Вы, вероятно, правы, что вы не получите бесформенного решения, чтобы избежать бокса. Содержит ли ваше решение аргументы для f? - person ziggystar; 06.12.2012
comment
@ziggystar - Извините, я запутался в вопросах! Может быть, вы могли бы использовать shapeless здесь, и это было бы хорошо. В этом случае вы бы упаковали аргументы; вам нужно специализироваться, чтобы избежать этого. (Полная специализация на четырех аргументах дает порядка 10 000 классов, так что это неразумно.) - person Rex Kerr; 06.12.2012