Сопоставление шаблонов с конъюнкциями (PatternA и PatternB)
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
) - должен ли такой комбинатор быть добавлен в стандартную библиотеку?
обновление
Меня только что спросили, как компилятор интерпретирует 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`.
2 ответа:
Мне очень нравится этот трюк. Я не знаю ни одного существующего способа сделать это, и я не предвижу никаких проблем с этим-что, впрочем, не так уж много значит. Я не могу придумать никакого способа создать
Not
.Что касается добавления его в стандартную библиотеку... возможно. Но я думаю, что это немного трудно. С другой стороны, как насчет того, чтобы уговорить людей Scalaz включить его? Это больше похоже на их собственный бейливик.
возможной проблемой с этим является раздутый перевод, который генерирует сопоставитель шаблонов. Вот это перевод примера программы, сгенерированной с помощью
scalac -print
. Даже-optimise
не удается упроститьif (true) "_" else throw new MatchError()
выражения.большие совпадения шаблонов уже генерируют больше байт-кода, чем разрешено для одного метода, и использование этого комбинатора может усилить эту проблему.
если
&&
был встроен в язык, возможно, перевод может быть умнее. Кроме того, небольшие улучшения в-optimise
могу помочь.