Это правило, которое unapply всегда будет возвращать Option? - PullRequest
5 голосов
/ 14 декабря 2009

Я пытался создать метод unapply для использования в сопоставлении с образцом, и я пытался заставить его возвращать что-то отличное от Option, однако, Eclipse показывает это как ошибку. Является ли правилом, что unapply должен возвращать Option[T]?

РЕДАКТИРОВАТЬ: вот код, который я пытаюсь использовать. Я переключил код из предыдущего раздела, чтобы unapply возвращал логическое значение

import java.util.regex._

object NumberMatcher {
  def apply(x:String):Boolean = {
    val pat = Pattern.compile("\\d+")
    val matcher = pat.matcher(x)
    return matcher.find
  }

  def unapply(x:String):Boolean = {
    val pat = Pattern.compile("\\d+")
    val matcher = pat.matcher(x)
    return matcher.find
  }
}

object x {
  def main(args : Array[String]) : Unit = {
    val strings = List("geo12","neo493","leo")
    for(val str <- strings) {
      str match {
        case NumberMatcher(group) => println(group)
        case _ => println ("no")
      }
    }
  }
}

Затмение говорит wrong number of arguments for object NumberMatcher. Почему это?

Ответы [ 4 ]

9 голосов
/ 15 декабря 2009

Если вы хотите вернуть что-то с unapply, верните это внутрь Some. Возвращение Boolean просто проверяет, может ли совпадение быть выполнено.

Вот как переводится соответствие шаблона:

str match { 
  case NumberMatcher(group) => println(group)
  case _ => println("no")
}

Предполагая, NumberMatcher возвращает Option[...], он будет делать:

val r1 = NumberMatcher.unapply(str)
if (r1 != None) {
  val group = r1.get
  println(group)
} else {
  println("no")
}

Если NumberMatcher возвращает логическое значение, вы можете получить его. В этом случае вот что происходит:

str match { 
  case NumberMatcher() => println("yes")
  case _ => println("no")
}

становится

val r1 = NumberMatcher.unapply(str)
if (r1) {
  println("yes")
} else {
  println("no")
}

Обратите внимание, что это очень поверхностное объяснение. Совпадения с вариантами могут проверять константы, иметь дополнительные условия защиты, альтернативы, использовать unapply рекурсивно, использовать unapplySeq и т. Д. Здесь я только показываю очень простое использование для решения конкретного вопроса. Я настоятельно рекомендую поискать более полное объяснение сопоставления с образцом.

7 голосов
/ 14 декабря 2009

Взгляните на этот пример еще раз. Я цитирую

Тип возврата неприменяемого должен быть выбран следующим образом:
* Если это просто проверка, верните логическое значение. Например, даже ()
* Если он возвращает единственное вспомогательное значение типа T, вернуть Option [T]
* Если вы хотите вернуть несколько вложенных значений T1, ..., Tn, сгруппируйте их в необязательный кортеж Option [(T1, ..., Tn)].

1 голос
/ 15 декабря 2009

Когда вы определили unapply для возврата Boolean, вы указывали, что в шаблоне нет подстановочных знаков для сопоставления (или привязки). Таким образом, оператор case для этого экстрактора должен быть case NumberMatcher => println(str), а присвоение ему переменной для заполнения неверно.

В качестве альтернативы, чтобы сделать case NumberMatcher(group) => println(group), вам нужно определить unapply(), чтобы вернуть Option[String]

0 голосов
/ 03 марта 2015
package com.tutorial.extracters
object ExtracterwithBooleanReturnType extends App {
import java.util.regex._
object NumberMatcher {
  def apply(x: String*) = {
    x
  }
  def unapply(x: String): Option[Boolean] = {
    val pat = Pattern.compile("\\d+")
    val matcher = pat.matcher(x)
    return Some(matcher.find)
 }
}

val strings = NumberMatcher("geo12", "neo493", "leo")
for (str <- strings) {
  str match {
  case NumberMatcher(group) => println(group)
  case _ => println("no")
}
}
}

мы можем достичь этого и с помощью приведенного выше кода

...