有人可以给我一个更简单的解决方案,以下代码(在给定结构0xFC :: len :: payload :: … :: 0x0A :: 0x0D的情况下展开整数列表):
object Payload { def unapply(z: List[Int]): Option[List[Int]] = if (z.length == z.head + 1) Some(z tail) else None } object EndToken { def unapply(z: List[Int]): Option[List[Int]] = z.reverse match { case 0x0D :: 0x0A :: tail => Some(tail.reverse) case _ => None } } object Message { def unapply(z: List[Int]): Option[List[Int]] = z match { case 0xFC :: EndToken(x) => Some(x) case _ => None } } object Main extends App { val x = List(0xFC,0x03,0x01,0x02,0x0A,0x0D) x match { case Message(Payload(payload)) => println (payload) case _ => println("No match") } }
就像是:
object Message { def unapply(z: List[Int]): Option[List[Int]] = z match { case 0xFC :: Payload(x) :: 0x0A :: 0x0D => Some(x) case _ => None } }
但是,当然,::期待元素,而不是列表,所以它不起作用……
解决方法
这是我的解决方案(虽然重新阅读,我认为这就像丹尼尔的解决方案).它基于中缀操作模式,其中模式op(p,q)是相同的p op q.
运算符以:具有与::相同的前导,并以:结束于右边. (len,payload):!:tail与:!:((len,payload),tail)相同.基于长度的有效负载提取的实现有点复杂,但主要是因为我只想遍历列表一次.
object :!: { type LengthPayload = (Int,List[Int]) // (len,payload) // returns ((len,unparsed) def unapply(z: List[Int]): Option[(LengthPayload,List[Int])] = { if (z == Nil) None else { val len = z.head // use ListBuffer to traverse the list only once val buf = collection.mutable.ListBuffer[Int]() def take(l: Int,list: List[Int]): Option[(LengthPayload,List[Int])] = { list match { case Nil if l > 0 => None case _ if l == 0 => Some((len,buf.toList),list) case _ => buf += list.head; take(l - 1,list.tail) } } take(len,z.tail) } } }
然后消息变得更简单(视觉上):
object Message { def unapply(z: List[Int]): Option[List[Int]] = z match { case 0xFC :: (len,payload) :!: 0x0A :: 0x0D :: Nil => Some(payload) case _ => None } }
结果:
val x = List(0xFC,0x0D) x match { case Message(payload) => println(payload) case _ => println("No match") } // List(1,2,3)
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。