Reputation: 13342
Reading this, I still have questions about unapply()
that returns Boolean
.
If take a look at Scala Programming Book (2nd edition), page 602. There is an example:
case Email(Twice(x @ UpperCase()), domain) => ...
Where UpperCase defined as an object that has unapply()
returning Boolean
and does not have apply()
object UpperCase {
def unapply(s:String): Boolean = s.toUpperCase == s
}
Where Twice
is something like this:
object Twice {
def apply(s:String): String = s + s
...
The questions are (must be too many, sorry for that):
How does UpperCase().unapply(..) works here?
If I pass: [email protected]
, then x
in first code snippet = 'DI'.. then we use '@' ..to bind 'x' to pass it to UpperCase.unapply
to invoke unapply(x)
i.e unapply('DIDI')
(?) Then it returns True
.
But why not Option
? I tend to think that unapply
returns Option
.. kind of one way how it works. That's probably because usually Option
wraps some data, but for simple case we should NOT wrap boolean? And because we do not have apply()?
What the difference, when use Boolean
/ Option
? Based on this example.
And this syntax: x @ UpperCase()
, is it supposed to substitute value match case
(is that way how I suppose to read it?) syntax if we are matching inside one particular case
? It doesn't seems as unified way/syntax of doing this.
Usually syntax like (assuming that x,y is Int): case AA(x @ myX, y) => println("myX: " + myX)
says that x
binds to myX
, basically myX
is alias to x
.. in this case. But in our case - x @ UpperCase()
. x
binds to UpperCase().unapply()
.. putting x
as parameter. I mean binding here is quite abstract/wide notion..
Upvotes: 3
Views: 2737
Reputation: 39577
This is not so simple.
The behavior of "boolean test" match just changed in the latest milestone:
apm@mara:~/clones/scala$ ./build/pack/bin/scala
Welcome to Scala version 2.11.0-20130911-042842-a49b4b6375 (OpenJDK 64-Bit Server VM, Java 1.7.0_25).
Type in expressions to have them evaluated.
Type :help for more information.
scala>
scala> object OK { def unapply(s: String) = Some(s) filter (_ == "OK") }
defined object OK
scala> import PartialFunction._
import PartialFunction._
scala> cond("OK") { case OK() => true }
<console>:12: error: wrong number of patterns for object OK offering String: expected 1, found 0
cond("OK") { case OK() => true }
^
<console>:12: error: wrong number of patterns for object OK offering String: expected 1, found 0
cond("OK") { case OK() => true }
^
scala> cond("OK") { case OK(x) => true }
res1: Boolean = true
scala> :q
Previously, you could use the extractor without extracting any fields, just for a "boolean test", even though the result of the unapply
is not Boolean
:
apm@mara:~/clones/scala$ scalam
Welcome to Scala version 2.11.0-M4 (OpenJDK 64-Bit Server VM, Java 1.7.0_25).
Type in expressions to have them evaluated.
Type :help for more information.
scala> import PartialFunction._
import PartialFunction._
scala> object OK { def unapply(s: String) = Some(s) filter (_ == "OK") }
defined object OK
scala> cond("OK") { case OK() => true }
res0: Boolean = true
scala> cond("OK") { case OK(x) => true }
res1: Boolean = true
Here is some discussion and here is the change in the way extractor signatures are processed.
Upvotes: 2
Reputation: 843
This is simple:
1) If you return Boolean, your unapply just tests matching query
scala> object UpperCase {
| def unapply(s: String) = s.toUpperCase == s
| }
defined module UpperCase
scala> "foo" match {
| case UpperCase() => true
| case _ => false
| }
res9: Boolean = false
2) If you return Option[T], you create an extractor, which unwraps T
scala> object IsUpperCase {
| def unapply(s: String) = Option(s).map(x => x.toUpperCase == x)
| }
defined module IsUpperCase
scala> "FOO" match {case IsUpperCase(flag) => flag}
res0: Boolean = true
Upvotes: 6