Классы Case, сопоставление с образцом и карри конструкторы в Scala - PullRequest
13 голосов
/ 01 сентября 2011

Они, кажется, не так хорошо смешиваются:

abstract class A
case class B (var a: Int)(var b: String) extends A
case class C extends A

Следующее не будет работать:

B(1)("1") match {
  case B(a)(b) => print("B")
  case C() => print("C")
}

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

Ответы [ 3 ]

12 голосов
/ 01 сентября 2011

Если вы посмотрите на сигнатуру неприменяемой функции, созданной для класса B, вы увидите, что это: unapply(x$0: Q): Option[Int]. Таким образом, функция unapply работает с первым диапазоном параметров классов case.

Это подтверждается спецификацией scala (§5.3.2):

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

Очевидно, что через экстрактор доступен только первый раздел параметров.

Несколько обходных путей:

  • Не используйте ваши параметры
  • используйте сопоставление с шаблоном, если хотите проверить 2 значения: case x@B(3) if x.b == "bazinga" => ...
  • используйте обычный класс и определите свой собственный объект-компаньон с вашим собственным apply / unapply
7 голосов
/ 01 сентября 2011

Что с этим не так?

def m(a: A) = a match {
  case b: B => print("B")
  case c: C => print("C")
}

Я спрашиваю только потому, что вы не просили больше функциональности, чем эта.

РЕДАКТИРОВАТЬ

Это может помочь:

object Dog {
   def apply(name: String)(size: Int) = new Dog(name)(size)
   def unapply(dog: Dog) = Some(dog.name, dog.size)
}
class Dog(val name: String)(var size: Int)

Теперь вы можете создавать собак так:

new Dog("Snoopy")(10) 

или вот так:

Dog("Snoopy")(10)

Но когда вышаблон соответствия на собаках конструктор шаблон не карри.

Dog("Snoopy")(10) match {
   case Dog(a, b) => // do sth with a or b
}
2 голосов
/ 01 сентября 2011

Вы можете использовать обычный класс case и просто определить фабричный метод с более чем одним списком параметров.

...