Как сопоставить шаблон с несколькими списками аргументов?

Рассмотрим этот класс:

class DateTime(year: Int, month: Int, day: Int)(hour: Int, minute: Int, second: Int)

как бы unapply метод выглядит так, если бы я хотел сопоставить что-то вроде:

dt match {
  case DateTime(2012, 12, 12)(12, _, _) => // December 12th 2012, 12 o'clock
  /* ... */
}

Я попробовал это:

def unapply(dt: DateTime) = 
  Some((dt.year, dt.month, dt.day),(dt.hour, dt.minute, dt.second))

Но это не сработало.

3 ответа

Решение

Классы case совпадают (и выполняют другие свои изящные действия) только с первым набором параметров:

scala> case class A(i: Int)(j: Int) { }
defined class A

scala> A(5)(4) match { case A(5) => "Hi" }
res14: java.lang.String = Hi

scala> A(5)(4) == A(5)(9)
res15: Boolean = true

Если это не класс case, вы можете определить, что unapply может быть чем угодно, так что это действительно зависит от разработчика класса. По умолчанию нет отмены, поэтому вы можете сопоставить только по типу.

Если вы хотите использовать отличные функции класса case, в том числе возможность сопоставления и равенства во всем, но с некоторым типом деления, вы можете вложить классы case:

case class Time(hour: Int, minute: Int, second: Int) { }
case class Date(year: Int, month: Int, day: Int) { }
case class DateTime(date: Date, time: Time) { }

scala> val dt = DateTime(Date(2011,5,27), Time(15,21,50))
scala> dt match { case DateTime(Date(2011,_,_),Time(h,m,50)) => println(h + ":" + m) }
15:21

Просто, основываясь на ответе Рекса, вы можете не только сопоставлять шаблоны по первому блоку параметров, но и с таким поведением.

Более интересный вопрос: почему классы падежей, как алгебраические типы данных, даже поддерживают несколько списков параметров...

Нет достаточно веских оснований для добавления специального поведения для классов дел, и несколько списков параметров оказываются довольно полезными. В производственном коде это средство часто используется только для предоставления неявных аргументов, которые вы, естественно, не захотите сопоставлять с шаблоном.

Вероятно, это не сработало, потому что в Scala нет оператора запятой, и вы возвращаетесь Some((a,b),(x,y)) от экстрактора. Если вы использовали Some(((a,b,c),(x,y,z))) вместо этого (т.е. Tuple2[Tuple3[A,B,C],Tuple3[X,Y,Z]] Я думаю, что это, вероятно, сработает.

Другие вопросы по тегам