Reputation: 63172
Normal successful) case: correct number of target variables for destructuring:
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
Unsupported (?) Cases
a) Fewer target variables for the destructuring: the intention would be to capture the "other" parameters into one Sequence-Like variable:
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) More target variables than source variables for the destructuring: intention would be to have optional source variables
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)
Upvotes: 1
Views: 58
Reputation: 2913
List
has a deconstructing ::
operator which provides support for 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)
The issue with providing this operator for other data structures in standard library is that other data structures do not have similar performance characteristics. Take a similarly defined operator against 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)
I don't necessarily promote this, but you could define a similar operator which provides support for use case 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()
Upvotes: 1