简体   繁体   中英

Match a tuple of unknown size in scala

Is there way to partially match a tuple without having to specify the size? For example, if I had a tuple

val v = ( "Dr", "John","H", "Watson") 

I'd like to be able to do something like :

v match { 
   case ( "Dr", : _*) => "What's up, Doc?"
   case ( "Mr", name,   :_*) =>  s"Welcome, Mr. ${name}"
   case _ => "Have we met?"
} 

This doesn't compile, :_* normally means an undetermined number of parameters, but can't be used in this case apparently. The idea would be to be able to use this matcher for any tuple bigger than 2. I know i can do it converting v to a List (for example) first, just want to know if it's possible to do it with a tuple .

EDIT : the most information I found on the web is this discussion , which dates back to scala 2.8, so I'm gonna with the 'No, you can't' answer.

Tuples are structures for heterogeneous types. As such, they implement the productIterator trait, so you could do:

v.productIterator.toList match { 
  case "Dr" :: _ => "What's up, Doc?"
  case "Mr" :: name :: _ =>  s"Welcome, Mr. ${name}"
  case _ => "Have we met?"
}

But your example really looks like you want a Seq[String] straight away. Is there any reason for wishing to use tuples?

This can be done using shapeless 's conversions from tuples to HLists ,

scala> import shapeless._
import shapeless._

scala> import Tuples._
import Tuples._

scala> val v = ( "Dr", "John","H", "Watson")
v: (String, String, String, String) = (Dr,John,H,Watson)

scala> v.hlisted match {
     |   case "Dr" :: _ => "What's up Doc?"
     |   case "Mr" :: name :: _ => s"Welcome, Mr. ${name}"
     |   case _ => "Have we met?"
     | }
res0: String = What's up Doc?

Although it's not visible in the above example, note that where possible full static type information is maintained for the names bound in the case clauses, for example,

scala> (23, "foo", true).hlisted match {
     |   case i :: s :: b :: HNil => if(b) i+s.length else 0
     |   case _ => -1
     | }
res1: Int = 26

Try this:

case tuple:Product => {
    tuple.productIterator.toList match {
        case (head::rest) => ...

    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM