微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

模式匹配Scala中列表的结尾/中间

有人可以给我一个更简单的解决方案,以下代码(在给定结构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 举报,一经查实,本站将立刻删除。

相关推荐