Сопоставление с образцом с соединениями (PatternA И PatternB)

У Scala есть функция языка для поддержки разъединений в сопоставлении с образцом ('Альтернативы Шаблона'):

x match {
    case _: String | _: Int => 
    case _ =>
}

Однако я часто должен инициировать действие, если исследование удовлетворяет PatternA и PatternB (соединение).

Я создал шаблон combinator '&&', который добавляет эту возможность. Три небольших строки, которые напоминают мне, почему я люблю 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 _ => "_"
}

Точки для обсуждения

  1. Существует ли существующий способ сделать это?
  2. Есть ли проблемы с этим подходом?
  3. Этот подход может создать какой-либо другой полезный combinators? (например, Not)
  4. Такой combinator должен быть добавлен к стандартной библиотеке?

ОБНОВЛЕНИЕ меня просто спросили, как компилятор интерпретирует 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 likeBoolean#&&inval b = истинная && ложь && верный'.

60
задан 7 revs, 3 users 64% 9 February 2017 в 17:23
поделиться

2 ответа

Мне очень нравится этот трюк. Я не знаю какого-либо существующего способа сделать это, и я не предвижу никаких проблем с этим, хотя это не имеет большого значения. Я не могу придумать способ создать Not .

Что касается добавления его в стандартную библиотеку ... возможно. Но я думаю, что это немного сложно. С другой стороны, как насчет того, чтобы убедить людей Scalaz включить его? Это больше похоже на их собственный залог.

13
ответ дан 24 November 2019 в 17:55
поделиться

Возможная проблема с этим - раздутый перевод, который генерирует паттерн-матчинг. Вот перевод примера программы, созданный с помощью scalac -print. Даже -optimise не помогает упростить выражения if (true) "_" else throw new MatchError().

Большие совпадения шаблонов уже генерируют больше байткода, чем допустимо для одного метода, и использование этого комбинатора может усилить эту проблему.

Если бы && был встроен в язык, возможно, перевод мог бы быть более умным. Также могут помочь небольшие улучшения в -optimise.

11
ответ дан 24 November 2019 в 17:55
поделиться
Другие вопросы по тегам:

Похожие вопросы: