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

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

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

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

5 ответов

Решение

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

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

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

Как не отвечающий духу вопроса, который спрашивал, как включить предикаты в предложение о совпадении, в этом случае предикат может быть разложен до 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) обещает только, что неравные результаты будут больше или меньше нуля. в Java Comparable#compareTo(T) определяется аналогично Scala. Случается, что традиционно использовать 1 и -1 для положительных и отрицательных значений соответственно, как это делает текущая реализация Scala, но такое предположение невозможно сделать без некоторого риска того, что реализация изменится снизу.

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

(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).

Несмотря на то, что все приведенные выше и ниже ответы отлично отвечают на исходный вопрос, некоторую дополнительную информацию можно найти в документации https://docs.scala-lang.org/tour/pattern-matching.html, но они не подходят для моего случая но так как этот ответ на stackru является первым предложением в Google, я хотел бы опубликовать свой ответ, который является угловым случаем вопроса выше.
Мой вопрос:

  • Как использовать охранник в выражении соответствия с аргументом функции?

Что можно перефразировать:

  • Как использовать оператор if в выражении соответствия с аргументом функции?

Ответ - пример кода ниже:

    def drop[A](l: List[A], n: Int): List[A] = l match {
      case Nil => sys.error("drop on empty list")
      case xs if n <= 0 => xs
      case _ :: xs => drop(xs, n-1)
    }

ссылка на скрипку Scala: https://scalafiddle.io/sf/G37THif/2 как вы можете видеть case xs if n <= 0 => xs оператор может использовать n(аргумент функции) с оператором guard(if).

Я надеюсь, что это помогает кому-то, как я.

Сопоставление шаблонов в Scala позволяет определить собственный экстрактор. В этом случае вы можете просто определить новый экстрактор:

      class GreaterThan(n: Int) {
  def unapply(i: Int) = i > n
}

val GreaterThan10 = GreaterThan(10)

a match {
  case 10 => ???
  case GreaterThan10() => ???
  case _ => ???
}

или просто используйте защиту шаблона.

Другие вопросы по тегам