开发者

Is it a rule that unapply will always return an Option?

I tried to create an unapply method to use in pattern matching, and I tried to make it return something different than Option, however, Eclipse shows that as an error. Is it a rule that unapply must return an Option[T] ?

EDIT: here's the code I'm trying to use. I switched the code from the previous section so that unapply returns a Boolean

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)
    r开发者_如何学Pythoneturn 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")
      }
    }
  }
}

Eclipse says wrong number of arguments for object NumberMatcher. Why is that?


If you want to return something with unapply, return it inside Some. Returning Boolean just tests if the match can be made or not.

Here is how a pattern matching is translated:

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

Assuming NumberMatcher returns Option[...], it will do:

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

If NumberMatcher returns Boolean, then you can have it receive something. In that case, this is what happens:

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

becomes

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

Note that this is a very superficial explanation. Case matches can test for constants, have additional guard conditions, alternatives, use unapply recursively, use unapplySeq, etc. Here I'm only showing very basic usage to address a specific question. I strongly advise searching for a fuller explanation of pattern matching.


Take a look at this example again. I quote

The return type of an unapply should be chosen as follows:
* If it is just a test, return a Boolean. For instance case even()
* If it returns a single sub-value of type T, return a Option[T]
* If you want to return several sub-values T1,...,Tn, group them in an optional tuple Option[(T1,...,Tn)].


When you defined unapply to return a Boolean, you were indicating that the pattern doesn't have any wildcards to match (or bind). So the case statement for this unextractor should be case NumberMatcher => println(str), and giving it a variable to fill is wrong.

Alternatively, to make case NumberMatcher(group) => println(group) you need to define unapply() to return Option[String]


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")
}
}
}

we can achieve this with above code as well

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜