我有一系列元素,特别是字节,我希望将它们匹配到更高级别的内容,例如: 16位整数。天真的方法看起来像这样:
val stream: Seq[Byte] = ???
def short(b1: Byte, b0: Byte): Short = ???
stream match {
case Seq(a1, a0, b1, b0, _*) => (short(a1, a0), short(b1, b0))
// ...
}
我设法做的是这样,使用object short_::
unapply
方法:
stream match {
case a short_:: b short_:: _ => (a, b)
// ...
}
但是,我真的不能说我喜欢这里的语法,因为它看起来不像常规模式匹配。我写这样的东西会更高兴:
stream match {
case Short(a) :: Short(b) :: _ => (a, b)
// ...
}
当然,使用标识符Short
和::
可能很难/一个坏主意,但我认为这是为了解决这个问题的重点。
是否可以编写自定义模式匹配代码,产生与此类似的语法?我在这里限制自己到流的固定宽度内容(虽然不是一个宽度:例如Short和Int都应该是可能的),但我需要能够匹配流的其余部分,如{{ 1}}或:: tail
。
答案 0 :(得分:2)
试试这个
object ::: {
def unapply(seq: Seq[Byte]): Option[(Int, Seq[Byte])] = {
if(seq.size > 1) Some(seq(0) * 256 + seq(1), seq.drop(2))
else None
}
}
val list = List[Byte](1,2,3,4,5,6,7,8)
list match {
case a ::: b ::: rest => println(a + ", " + b + ", " + rest)
}
你也可以混合使用字节,短路和整数。
object +: {
def unapply(seq: Seq[Byte]): Option[(Byte, Seq[Byte])] = {
if(seq.size > 0) Some(seq.head, seq.tail)
else None
}
}
object ++: {
def unapply(seq: Seq[Byte]): Option[(Short, Seq[Byte])] = seq match {
case a +: b +: rest => Some(((a&0xFF) << 8 | (b&0xFF)).toShort, rest)
case _ => None
}
}
object +++: {
def unapply(seq: Seq[Byte]): Option[(Int, Seq[Byte])] = seq match {
case a ++: b ++: rest => Some((a&0xFFFF) << 16 | (b&0xFFFF), rest)
case _ => None
}
}
val list = List[Byte](1,2,3,4,5,6,7,8,9,10,11,12)
list match {
case a +: b ++: c +++: rest => println(a + ", " + b + ", " + c + ", " + rest)
}
+:表示左边的变量是一个字节,++:表示左边的变量是short,+++表示int。顺便说一句。出于某种原因,只有当对象的名称以&#34;:&#34;。
结尾时,这才有效