Robię dopasowywanie do niektórych klas przypadków i chciałbym poradzić sobie z dwoma z nich w ten sam sposób. Coś takiego:
abstract class Foo
case class A extends Foo
case class B(s:String) extends Foo
case class C(s:String) extends Foo
def matcher(l: Foo): String = {
l match {
case A() => "A"
case B(sb) | C(sc) => "B"
case _ => "default"
}
}
Ale kiedy to robię, pojawia się błąd:
(fragment of test.scala):10: error: illegal variable in pattern alternative
case B(sb) | C(sc) => "B"
Mogę sprawić, że będzie działać, usuwając parametry z definicji B i C, ale jak mogę dopasować je do parametrów?
scala
pattern-matching
timdisney
źródło
źródło
case A(x) | B(x) => println(x)
pozwolenie, gdy typx
jest ustawiony na górną granicę w systemie typów wszystkiego, co produkują A (x) i B (x).Jest kilka sposobów na osiągnięcie tego, do czego dążysz, jeśli masz pewne podobieństwa między klasami przypadków. Pierwsza polega na tym, aby klasy przypadków rozszerzały cechę, która deklaruje podobieństwo, a druga to użycie typu strukturalnego, który eliminuje potrzebę rozszerzania klas przypadków.
Metoda typu strukturalnego generuje ostrzeżenie o skasowaniu, które obecnie nie jestem pewien, jak wyeliminować.
źródło
Cóż, to naprawdę nie ma sensu, prawda? B i C wykluczają się wzajemnie, więc sb lub sc zostają powiązane, ale nie wiesz, które z nich, więc potrzebujesz dalszej logiki wyboru, aby zdecydować, którego użyć (zakładając, że były one powiązane z Option [String], a nie struna). Więc nic na tym nie zyskuje:
Albo to:
źródło
args match { case Array("-x", hostArg) => (hostArg, true); case Array(hostArg, "-x") => (hostArg, true) }
Jednak widzę, że to nie jest typowy przypadek i że utworzenie metody lokalnej jest alternatywą. Jeśli jednak alternatywa jest wygodna, nie ma sensu mieć alternatywnych przypadków. W rzeczywistości w niektórych dialektach ML masz podobną funkcję i nadal możesz wiązać zmienne, o ile (IIRC) każda zmienna jest powiązana z tym samym typem w obu alternatywach.