I have library method taking variable argument list and producing data
class Data
def process(elems: String*): Data = new Data
and I want my strings to be implicitly converted to Data
implicit def strToData(ts: String): Data = process(t)
so I can write something like
val data: Data = "one"
but I want tuples of strings to be implicitly converted too. I've added another implicit
implicit def strsToData(ts: String*): Data = process(ts: _*)
it compiles fine, but conversion fails
val data: Data = ("one", "two")
val dat3: Data = ("one", "two", "three")
val dat4: Data = ("one", "two", "three", "four")
with
found : Seq[java.lang.String]
required: this.Data
val data: Data = Seq("one", "two")
Is there any way to convert tuples implicitly, or a reason why it can be achieved?
Update: Tuples can be of any arity.
ts: String*
is not a tuple, but an Iterable
. You can't convert iterable to tuple, because tuple is a static type and its arity is resolved at compile time. Emil H answered how you can do an implicit conversion from tuple. Transparent implicit conversions from one type to another type is a common pitfall and are greatly discouraged. Instead you should apply a "wrapper" approach, or use "Value Classes" since Scala 2.10:
In Scala 2.9:
implicit def stringStringTupleExtender (ts : (String, String)) =
new {
def data = process(ts)
}
In Scala 2.10:
implicit class StringStringTupleExtender (val ts : (String, String)) extends AnyVal {
def data = process(ts)
}
Then you'll use it like so:
val data : Data = ("sdf", "lsdfj").data
val data1 : Data = "sdf".data // if you do the same for String
If you're looking for dynamically resolving any input collection, then, guess what, you should use a collection, not a tuple.
In Scala 2.9
implicit def seqExtender (ts : Seq[String]) =
new {
def data = process(ts)
}
Usage:
val data : Data = Seq("sdf", "lsdkfjsdl", "ldsfjk").data
While all the warnings in @NikitaVolkov's answer apply in double force, you can write a version that accepts any arity of tuple, as well as any case class:
implicit def prod2data(Product p): process((p.productIterator.toSeq):_*)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With