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

爱⌒轻易说出口 提交于 2020-01-14 08:40:49

问题


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

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


回答1:


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.




回答2:


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




回答3:


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]




回答4:


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



来源:https://stackoverflow.com/questions/1903341/is-it-a-rule-that-unapply-will-always-return-an-option

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!