1

Given a Tuple3, e.g. ("one", "two", "three") I want to obtain tuple2, which contains only first two elements ("one", "two").

One way to do this is something like that:

val (one, two, _) = ("one", "two", "three")
val result = (one, two)

But what if I want to do a similar thing getting tuple14 from tuple16? Boilerplate.

UPDATE:

More specific usecase (func2 and func3 can't be changed).

def func3(one: String, two: String, three: String) = println("Do something") 
def func2(one: String, two: String) = println("Do something 2")

val originalTuple = ("one", "two", "three")
val newTuple = ???

(func3 _).tupled(originalTuple)
(func2 _).tupled(newTuple)
ov7a
  • 1,497
  • 4
  • 15
  • 34
  • 5
    Don't use tuples? Treating tuples as (sort of) indexed sequences is never going to work well (although shapeless does its best to help) – The Archetypal Paul Nov 26 '14 at 10:55
  • Unfortunately, this tuple is argument list for function which I can't change. According to http://stackoverflow.com/questions/14722860/convert-a-scala-list-to-a-tuple list can't be converted to tuple. And I don't know a way to pass list of arguments to function. – ov7a Nov 28 '14 at 09:11
  • " And I don't know a way to pass list of arguments to function" Please explain more what you mean by this (maybe in another question). it might b possible. – The Archetypal Paul Nov 28 '14 at 09:27
  • There is already a similar question: http://stackoverflow.com/questions/13546412/pass-function-arguments-from-a-iterable-in-scala – ov7a Nov 28 '14 at 09:42
  • And it has an answer :) – The Archetypal Paul Nov 28 '14 at 10:12
  • Once again: I can't change function. – ov7a Nov 28 '14 at 10:21
  • Please can you give the signature of that function, and the call you make to it? – The Archetypal Paul Nov 28 '14 at 10:22
  • To be slightly less cryptic, I was wondering if `Function.untupled` would help you out. But more details on your actual use case neded. – The Archetypal Paul Nov 28 '14 at 10:27
  • OK. then I don't understand why you don;t just call (e.g.) `func2(originalTuple._1, originalTuple._2)` or define a helper function to do that for you if that gets repeated a lot. – The Archetypal Paul Nov 28 '14 at 11:18
  • Imagine a function with 16 arguments. This will be a lot of dumb boilerplate code. Yes it can be localized in one function, but this function would be very ugly. I'm looking for more general solution. – ov7a Nov 28 '14 at 11:32
  • I still don't understand the use case. Is originaTuples also something you can't change? Is there more than one funcN you need to call? Are you always guaranteed the arguments to func N will be the firstN of the tuple? I can't help feeling that the expressed problen isn't the "real" issue (but I probably can't help so I'll stop now. SO is whining about extended chats in any case) – The Archetypal Paul Nov 28 '14 at 11:43

2 Answers2

7

You may try take/drop from Shapeless 2.0:

import syntax.std.tuple._

scala> (23, "foo", true).take(2)
res3: (Int, String) = (23,foo)

There is no such solution in standard library because normally you don't need it. Tuple with 16 different types/elements has no sense and is an obvious sign of bad style. Usually such tuples may be represented as nested case classes, but sometimes (very very rare) you may need such things to improve type safety. That's why Shapeless exists.

dk14
  • 22,206
  • 4
  • 51
  • 88
  • 2
    Don't forget `import syntax.std.tuple._` – acjay Nov 26 '14 at 14:14
  • This is nice, but I looking for some solution in standard library. – ov7a Nov 28 '14 at 09:06
  • there is no one because situation when you really need this is very rare - tuple with 16 different types/elements has no sense (and is a sign of a bad style). Usually it can be represented as several nested tuples/case classes. But sometimes (very very rare) you need it - that's why shapeless exists. – dk14 Nov 28 '14 at 11:44
  • Sounds quite reasonable. – ov7a Nov 28 '14 at 15:51
3

This will do ok for first two elements.

scala> val tuple3 = ("one","two","three")
tuple3: (String, String, String) = (one,two,three)

scala> (tuple3._1, tuple3._2)
res8: (String, String) = (one,two)
fada21
  • 3,188
  • 1
  • 22
  • 21
  • I think it's practically the same with example in my question. This will be boilerplate for tuple16. – ov7a Nov 28 '14 at 09:05
  • 2
    actually this is not same and is not boilerplate: `val tuple16 = (1,2,3,4,5,6,7,8,...,16); (tuple16._1, tuple16._2)`. The problem here (solving by Shapeless) is only if you want to get smtg like tuple14 from tuple16 but you didn't actually ask for that: `obtain tuple2, which contains only first two elements ("one", "two")` – dk14 Nov 28 '14 at 11:54
  • Oops. My bad. I actually mean tuple14 from tuple16. tuple2/3 question was just for simplifying. Thank you for noticing this. I've edited the question – ov7a Nov 28 '14 at 15:50