Scala имеет функцию языка для поддержки дизъюнкций при сопоставлении шаблонов ( "Альтернативы шаблонов" ):
x match {
case _: String | _: Int =>
case _ =>
}
Однако мне часто приходится запускать действие, если проверка удовлетворяет PatternA и PatternB (соединение.)
Я создал комбинатор шаблонов '& &' что добавляет эту возможность. Три маленькие строки, которые напоминают мне, почему я люблю Scala!
// Splitter to apply two pattern matches on the same scrutiny.
object && {
def unapply[A](a: A) = Some((a, a))
}
// Extractor object matching first character.
object StartsWith {
def unapply(s: String) = s.headOption
}
// Extractor object matching last character.
object EndsWith {
def unapply(s: String) = s.reverse.headOption
}
// Extractor object matching length.
object Length {
def unapply(s: String) = Some(s.length)
}
"foo" match {
case StartsWith('f') && EndsWith('f') => "f.*f"
case StartsWith('f') && EndsWith(e) && Length(3) if "aeiou".contains(e) => "f..[aeiou]"
case _ => "_"
}
Вопросы для обсуждения
- Есть ли способ сделать это?
- Есть ли проблемы с этим подходом?
- Может ли этот подход создать любые другие полезные комбинаторы? (например,
Not
) - Следует ли добавить такой комбинатор в стандартную библиотеку?
UPDATE
Меня просто спросили, как компилятор интерпретирует case A && B && C
. Это шаблоны инфикс-операторов (раздел 8.1.9 справочника Scala). Вы также можете выразить это стандартными шаблонами извлечения (8.1.7) в качестве &&(&&(A, B), C).' Notice how the expressions are associated left to right, as per normal infix operator method calls like
Boolean # && in
val b = true && & & false && true`.