任何允许在解构提取器中允许不同的源/目标参数计数的方法

时间:2014-05-07 22:03:15

标签: scala

正常成功)案例:用于解构的正确目标变量数量:

scala> val arr = Array("aa","bb",1,2,3,4,5)
scala> val Array(a,b,one,two,three,four,five) = arr
a: Any = aa
b: Any = bb
one: Any = 1
two: Any = 2
three: Any = 3
four: Any = 4
five: Any = 5

不受支持的(?)案例

a)解构的目标变量较少:意图是将“其他”参数捕获到一个类似序列的变量中:

scala> val arr = Array("aa","bb",1,2,3,4,5)
arr: Array[Any] = Array(aa, bb, 1, 2, 3, 4, 5)
val Array(a,b,one,two, others) = arr
scala.MatchError: [Ljava.lang.Object;@146a8d2 (of class [Ljava.lang.Object;)
        at .<init>(<console>:12)
        at .<clinit>(<console>)
        at .<init>(<console>:7)
        at .<clinit>(<console>)
        at $print(<console>)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:606)
        at scala.tools.nsc.interpreter.IMain$ReadEvalPrint.call(IMain.scala:734)

b)解构的源变量比目标变量更多:意图是可选的源变量

scala> val arr = Array("aa","bb",1,2,"optional-1","optional-2")
arr: Array[Any] = Array(aa, bb, 1, 2, optional-1, optional-2)

scala> val Array(a,b,one,two,optional1) = arr
scala.MatchError: [Ljava.lang.Object;@151c590 (of class [Ljava.lang.Object;)
        at .<init>(<console>:12)
        at .<clinit>(<console>)
        at .<init>(<console>:7)
        at .<clinit>(<console>)
        at $print(<console>)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:606)
        at scala.tools.nsc.interpreter.IMain$ReadEvalPrint.call(IMain.scala:734)
        at scala.tools.nsc.interpreter.IMain$Request.loadAndRun(IMain.scala:983)

1 个答案:

答案 0 :(得分:1)

List有一个解构::运算符,为a)提供支持

scala> val l = List("aa","bb",1,2,"optional-1","optional-2")
l: List[Any] = List(aa, bb, 1, 2, optional-1, optional-2)

scala> val a :: b :: one :: two :: others = l
a: Any = aa
b: Any = bb
one: Any = 1
two: Any = 2
others: List[Any] = List(optional-1, optional-2)

为标准库中的其他数据结构提供此运算符的问题是其他数据结构没有类似的性能特征。对Vector

采用类似定义的运算符
object :#: {
  def unapply[A](a: Vector[A]): Option[(A, Vector[A])] =
    if (a.length > 1) Some(a(0) -> a.drop(1))
    else None
}

scala> val a :#: b :#: one :#: two :#: others = v
a: Any = aa
b: Any = bb
one: Any = 1
two: Any = 2
others: Vector[Any] = Vector(optional-1, optional-2)

我不一定会宣传这一点,但您可以定义一个类似的运算符,它为用例b)提供支持

object :?: {
  def unapply[A](l: List[A]): Option[(Option[A], List[A])] =
    l match {
      case Nil => Some(None -> Nil)
      case a :: tail => Some(Some(a) -> tail)
    }
}

scala> val l = List("aa","bb")
l: List[String] = List(aa, bb)

scala> val a :?: optional1 :?: optional2 :?: rest = l
a: Option[String] = Some(aa)
optional1: Option[String] = Some(bb)
optional2: Option[String] = None
rest: List[String] = List()