在scala中匹配未知大小的元组

Chi*_*rlo 9 scala tuples pattern-matching

是否可以部分匹配a tuple而无需指定大小?例如,如果我有一个元组

val v = ( "Dr", "John","H", "Watson") 
Run Code Online (Sandbox Code Playgroud)

我希望能够做到这样的事情:

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

这不编译,:_*通常意味着未确定数量的参数,但显然不能在这种情况下使用.我的想法是能够将这个匹配器用于任何大于2的元组.我知道我可以先将它转换vList(例如),只是想知道是否有可能用它做tuple.

编辑:我在网上找到的信息最多是本次讨论,其历史可以追溯到2.8阶,所以我会用"不,你不能"的答案.

0__*_*0__ 11

元组是异构类型的结构.因此,他们实现了productIterator特性,所以你可以这样做:

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

但是你的例子看起来真的很像你想要的Seq[String].是否有任何理由希望使用元组?


Mil*_*bin 10

这可以通过从元组到无形的转换来完成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?
Run Code Online (Sandbox Code Playgroud)

虽然在上面的示例中不可见,但请注意,在case子句中绑定的名称可能会保留完整的静态类型信息,例如,

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