Вы не можете передавать параметры в соответствие, кроме как неявным образом, и экстрактор должен знать, что ему нужно извлечь.
Нельзя сильно упростить ваше решение.Вот альтернативный способ написания этого, но это больше вопрос предпочтения, чем что-либо еще.
object :>>: {
def unapply(xs: List[Int])(implicit size: Int): Option[(List[Int], List[Int])] =
if (xs.size >= size) Some(xs splitAt size)
else None
}
object :<<: {
def unapply(xs: List[Int]): Option[(List[Int], List[Int])] = xs match {
case size :: rest =>
implicit val len = size
rest match {
case payload :>>: tail => Some((payload, tail))
case _ => None
}
case _ => None
}
}
object Message {
def unapplySeq(xs: List[Int]): Option[List[Int]] = xs match {
case 0xFC :: payload :<<: 0x0A :: 0x0D :: Nil => Some(payload)
case _ => None
}
}
Редактировать: Примечание о двоеточиях для методов :<<:
и :>>:
.Они не нужны для последнего в этом коде, но они нужны для первого.
Двоеточие в конце идентификатора означает левую и правую ассоциативность.Это важно, потому что аргумент справа от ::
и :<<:
должен быть List
, но 0x0A
и 0x0D
не являются списками.Правая ассоциативность, однако, означает, что самый правый оператор применяется первым, а левые применяются к результату.Другими словами.0x0A :: (0x0D :: Nil)
вместо (0x0A :: 0x0D) :: Nil
.
Двоеточие в начале идентификатора требуется из-за приоритета.Даже при правильной ассоциативности неправильный приоритет превратит 0xFC :: payload <<: ...
в (0xFC :: payload) <<: ...
.
Обратите внимание, что я использую unapplySeq
, чтобы вернуть результаты в Message
, чтобы их можно было извлечь, как вList
.Это означает, однако, что вам нужно @ _*
, чтобы получить всю последовательность:
scala> List(0xFC, 0x03, 0x01, 0x02, 0x03, 0x0A, 0x0D) match {
| case Message(z @ _*) => println (z)
| case _ => println("No match")
| }
List(1, 2, 3)