Pattern Matching Array of Bytes

1.1k views Asked by At

This fails to compile:

Array[Byte](...) match { case Array(0xFE.toByte, 0xFF.toByte, tail @ _* ) => tail }

I can, however, compile this:

val FE = 0xFE.toByte
val FF = 0xFF.toByte 
bytes match { Array( FE, FF, tail @ _* ) => tail }

Why does the first case fail to compile but not the second case?

2

There are 2 answers

0
Rex Kerr On BEST ANSWER

Matching as currently implemented in Scala does not allow you to generate expressions inside your match statement: you must either have an expression or a match, but not both.

So, if you assign the values before you get into the match, all you have is a stable identifier, and the match works. But unlike almost everywhere else in Scala, you can't substitute an expression like 0xFE.toByte for the val FE.

Type inference will work, so you could have written

xs match { case Array(-2, -1, tail) => tail }

since it knows from the type of xs that the literals -2 and -1 must be Byte values. But, otherwise, you often have to do just what you did: construct what you want to match to, and assign them to vals starting with an upper-case letter, and then use them in the match.

There is no exceedingly good reason why it must have been this way (though one does have to solve the problem of when to do variable assignment and when to test for equality and when to do another level of unapply), but this is the way it (presently) is.

3
Eugene Ryzhikov On

Because what you see in the match is not a constructor but extractor. Extractors extracts data into variables provided. That is why the second case works - you provide variables there. By the way, you did not have to create them in advance.

More about extractors at http://docs.scala-lang.org/tutorials/tour/extractor-objects.html