4

I am writing a data structure (basically a hashmap) in Scala that will take one tuple (of possibly different number of arguments each time) and do something with it. To generically implement this, I defined a type:

type T <: Tuple1[_] with Tuple2[_,_] with Tuple3[_,_,_] with Tuple4[_,_,_,_] with Tuple5[_,_,_,_,_]

and then the data structure

val map = new HashMap[Int, T]

But this is ugly, since I have to change the type every time I have to handle more arguments in a tuple. Is there to define a generic tuple type?

Thanks, Y.K.

6
  • 2
    Maybe you will be happy with Product? Yes, it allows to pass-in not only tuples, but it is pretty generic Commented Dec 9, 2012 at 9:38
  • Why do you restrict the value type of your data structure specifically to tuples? Do you intend to exploit some property common to all tuple types? Commented Dec 9, 2012 at 10:28
  • Thank you for your replies. I restrict the ds to tuples, since this is what the user will eventually enter (e.g. (3, 4.5, "foo")), and i want to avoid type conversions. I could use Product yes, however then I would have to have a regexp matching for the different types when i get each T back right? Something like varT match { case (,) => ... case (,,_) => ... } and so on... right? Commented Dec 9, 2012 at 10:35
  • 2
    I'm not sure I understand exactly what you're trying to do, but generalizing over tuple arity (without giving up type safety) is painful in Scala without the help of something like a heterogenous list implementation (I'd recommend Shapeless's). Commented Dec 9, 2012 at 12:03
  • I don't see which type conversions would be eliminated. Can you point out some? If the user will eventually enter (subtypes of) Any, would restricting T to Any eliminate type conversions? Commented Dec 9, 2012 at 13:16

1 Answer 1

4

The first solution is to use Product, as said by @om-nom-nom. Indeed, it's the only common supertype of all tuples.

val map = Map.empty[Int, Product]
map + (2 -> ("a", "b"))

And then to use the methods productArity, productElement and productIterator to handle the returned value.

You can also use a map of list (or any indexed collection).

val map = Map.empty[Int, List[_]]
map + (3 -> ("a" :: "b" :: "c" :: Nil))
map + (2 -> List("a", "b"))

The last solution is not that convenient for the user, but at least you know exactly what collection you handle. You could also add an implicit.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.