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
精彩评论