Использование операторов сравнения в системе сопоставления с образцом Scala

131

Можно ли сопоставлять сравнение с помощью системы сопоставления шаблонов в Scala? Например:

a match {
    case 10 => println("ten")
    case _ > 10 => println("greater than ten")
    case _ => println("less than ten")
}

Второй аргумент case является незаконным, но я хотел бы указать "когда a больше".

  • 1
    Это также может быть использовано для проверки того, оценивает ли функция значение true, например, case x if x.size > 2 => ...
  • 2
    Важно понимать, что «шаблоны» слева от оператора => действительно являются «шаблонами». 10 в первом выражении case НЕ является целочисленным литералом. Таким образом, вы не можете выполнять операции (например,> проверить или сказать, что приложение функции isOdd (_)) слева.
Теги:
pattern-matching

4 ответа

245
Лучший ответ

После шаблона вы можете добавить охранник, т.е. if и логическое выражение:

a match {
    case 10 => println("ten")
    case x if x > 10 => println("greater than ten")
    case _ => println("less than ten")
}

Изменить: обратите внимание, что это более чем поверхностно отличается от размещения if после =>, потому что шаблон не будет соответствовать, если защита не соответствует действительности.

  • 2
    Бен, хороший ответ, это действительно иллюстрирует важность охраны паттернов.
25

В качестве ответа на вопрос, который задал вопрос о том, как включить предикаты в предложение соответствия, в этом случае предикат можно разделить до match:

def assess(n: Int) {
  println(
    n compare 10 match {
      case 0 => "ten"
      case 1 => "greater than ten"
      case -1 => "less than ten"
    })
}

Теперь документация для scala.math.Ordering.compare(T, T) promises только то, что не равные результаты будут больше или меньше нуля. Java Comparable#compareTo(T) указан аналогично Scala. Обычно принято использовать 1 и -1 для положительного и отрицательного значений соответственно, так как Scala текущая реализация, но можно "сделайте такое предположение без какого-либо риска изменения реализации из-под него.

  • 5
    Я не уверен, предлагаете ли вы это как реальное решение, но я настоятельно рекомендую против всего, что основано на недокументированном соглашении или предположении.
  • 1
    Именно так. Вот почему я написал «никто не может сделать такое предположение без некоторого риска», и квалифицировал мой ответ как «не ответ». Интересно рассмотреть, почему compare() и compareTo() не указывают 0, 1 и -1 в качестве своего кодомена.
Показать ещё 4 комментария
14

Решение, которое, на мой взгляд, намного читаемо, чем добавление охранников:

(n compare 10).signum match {
    case -1 => "less than ten"
    case  0 => "ten"
    case  1 => "greater than ten"
}

Примечания:

  • Ordered.compare возвращает отрицательное целое число, если оно меньше, положительное, если больше, и 0, если он равен.
  • Int.signum сжимает вывод от compare до -1 для отрицательного числа (менее 10), 1 для положительных (более 10), или 0 для нуля (равный 10).
-10

Использовать защитные устройства:

a match {
    case 10 => println("ten")
    case some if some > 10 => println("greater than ten")
    case _ => println("less than ten")
}

Ещё вопросы

Сообщество Overcoder
Наверх
Меню