Манипулирующие кортежи

есть ли способ манипулировать несколькими значениями кортежа без использования временной переменной и запуска нового оператора?

скажем у меня есть метод, который возвращает кортеж, и я хочу сделать что-то с тех значений inline.

например, если я хочу разделить строку в определенной точке и поменять местами

def backToFront(s: String, n:Int) = s.splitAt(n)...

Я могу сделать

val (a, b) = s.splitAt(n)
b + a 

(требуются временные переменные и новый оператор) или

List(s.splitAt(n)).map(i => i._2 + i._1).head

(работает, но кажется немного грязно, создавая один список элементов только для этого) или

s.splitAt(n).swap.productIterator.mkString

(работает для этого конкретного примера, но только потому, что есть swap метод, который делает то, что я хочу, так это не очень общий).

The zipped метод на кортежах, кажется, просто для кортежей списков.

еще один пример, как можно превратить кортеж ('a, 'b, 'c) на ('b, 'a, 'c) в одном заявлении?

4 ответов


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

о последнем примере не удалось найти ничего лучше, чем сопоставление шаблонов.

('a, 'b, 'c) match { case (a, b, c) => (b, a ,c) }

к сожалению, встроенные методы на кортежи мало.

может быть, вы хотите что-то подобное в вашей личной библиотеке,

def fold2[A, B, C](x: (A, B))(f: (A, B) => C): C = f(x._1, x._2)
def fold3[A, B, C, D](x: (A, B, C))(f: (A, B, C) => D): D = f(x._1, x._2, x._3)

с соответствующими неявными преобразованиями вы можете сделать,

scala> "hello world".splitAt(5).swap.fold(_ + _)
res1: java.lang.String = " worldhello"

scala> (1, 2, 3).fold((a, b, c) => (b, c, a))
res2: (Int, Int, Int) = (2,3,1)

альтернативой последнему выражению будет оператор "труба"|> (получить его от Scalaz или здесь),

scala> ('a, 'b, 'c) |> (t => (t._2, t._3, t._1))
res3: (Symbol, Symbol, Symbol) = ('b,'c,'a)

Это было бы неплохо, если бы не требуемое аннотации

scala> ("hello ", "world") |> (((_: String) + (_: String)).tupled)
res4: java.lang.String = hello world

Как насчет этого?

s.splitAt(n) |> Function.tupled(_ + _)

[ Edit: только что заметил, что ваши аргументы для функции отменены. В этом случае вам придется отказаться от синтаксиса заполнителя и вместо этого перейти к:s.splitAt(n) |> Function.tupled((a, b) => b + a) ]

для вашего последнего примера не могу придумать ничего лучше, чем шаблон (как показано на @4e6.)


С текущей версией развития бесформенные, вы можете достичь этого, не распаковывая кортеж:

import shapeless.syntax.std.tuple._

val s = "abcdefgh"
val n = 3

s.splitAt(n).rotateRight[shapeless.Nat._1].mkString("", "", "") // "defghabc"

Я думаю, вам не нужно ждать слишком долго (я бы сказал, Вопрос дней), прежде чем синтаксис методов последней строки очистится, и вы можете просто написать

s.splitAt(n).rotateRight(1).mkString