Scala patternmatching: do nothing for some cases - scala

I have to perform some actions based on cases in a pattern matching block, but only for selective cases, and nothing to be done for remaining. So is it ok to just return () for remaining cases? Something like this:
val x = ....
val y = ....
(x, y) match {
case (Some(number), Some(text)) => {
......
}
case (Some(number), None) => {
......
}
case (_, _) => () // do nothing
}

Depends what you mean by "ok". If you are asking if it will compile, you can easily answer that question yourself, by running a few snippets in a REPL and find out, that you don't even need to return a unit. Something like this works just fine:
"foo" match {
"bar" => "baz"
"bat" => 1500
_ =>
}
If however by "ok" you meant whether it is a good idea, then the answer is "probably not". As mentioned in the comments, this is not type-safe and also purely side-effecting and not referentially transparent. There is likely a better way to do what you want.

It's generally ok, if all the cases in a match result in Unit (spelled () in Scala), to have a case result in () to preserve exhaustivity.
That said, in this case, where you require the first Option to be defined to do anything, I would probably express this as:
x.foreach { number =>
y match {
case Some(text) =>
??? // note that { } aren't required in match and ??? is idiomatic for "some code here"
case None =>
???
}
}
Then again, I particularly dislike pattern matching on Option, so ymmv.

Related

Pattern matching using current object

I'm trying to match an Option, and test to see if it's a Some containing the object making the call. So the code I want to write looks like this:
methodReturningOption() match {
case Some(this) => doSomething()
case _ => doSomethingElse()
}
but that fails to compile, with the error
'.' expected but ')' found
I also tried using Some(`this`) which gives the error
not found: value this
I can make it work if I add a variable which refers to this
val This = this
methodReturningOption() match {
case Some(This) => doSomething()
case _ => doSomethingElse()
}
but that looks ugly and seems like an unpleasant workaround. Is there an easier way to pattern match with this as an argument?
I suppose you could try this:
methodReturningOption() match {
case Some(x) if x == this => doSomething()
case _ => doSomethingElse()
}
It looks like this is considered a special keyword and can't be used in that context.
Jack Leow's solution is probably the best - I'd recommend going with that since it's much more explicit. However as an alternative you can also create a variable point to 'this' using the following syntax. (Note the self => on the first line)
class Person { self =>
def bla() = methodReturningOption() match {
case Some(`self`) => ???
case _ => ???
}
}
This doesn't really answer the question, it's just a potential alternative syntax that may be useful to you.

How much optimization does Scala's pattern matcher perform?

Suppose I have a Scala match expression
foo match {
case Bar(Some(x)) => /* do something */
case Bar(None) => /* do something else */
}
How much optimization does the compiler do when it compiles the expression? In particular, does it emit multiple calls to Bar.unapply, or does it make a single call and match multiple times on the result?
You can check this yourself with a little code:
object Bar {
def unapply(x: Int): Option[Option[Int]] = {
println("Checking: " + x)
Some(None)
}
}
1 match {
case Bar(Some(x)) => println("do something")
case Bar(None) => println("do something else")
}
When you run it, you get:
Checking: 1
do something else
So it looks like Scala is not doing multiple calls to Bar.unapply even though the code looks like there would be multiple calls. This is good from the standpoint of efficiency, but you should probably avoid side-effects in your unapply methods that rely on them getting called multiple times per match-statement.
If you were worried about when the optimization happens and making it clear to the reader that the unapply is only being called once, you could split up the matches quite easily:
1 match {
case Bar(y) => y match {
case Some(x) => println("do something")
case None => println("do something else")
}
}

Processing Scala Option[T]

I have a Scala Option[T]. If the value is Some(x) I want to process it with a a process that does not return a value (Unit), but if it is None, I want to print an error.
I can use the following code to do this, but I understand that the more idiomatic way is to treat the Option[T] as a sequence and use map, foreach, etc. How do I do this?
opt match {
case Some(x) => // process x with no return value, e.g. write x to a file
case None => // print error message
}
I think explicit pattern matching suits your use case best.
Scala's Option is, sadly, missing a method to do exactly this. I add one:
class OptionWrapper[A](o: Option[A]) {
def fold[Z](default: => Z)(action: A => Z) = o.map(action).getOrElse(default)
}
implicit def option_has_utility[A](o: Option[A]) = new OptionWrapper(o)
which has the slightly nicer (in my view) usage
op.fold{ println("Empty!") }{ x => doStuffWith(x) }
You can see from how it's defined that map/getOrElse can be used instead of pattern matching.
Alternatively, Either already has a fold method. So you can
op.toRight(()).fold{ _ => println("Empty!") }{ x => doStuffWith(x) }
but this is a little clumsy given that you have to provide the left value (here (), i.e. Unit) and then define a function on that, rather than just stating what you want to happen on None.
The pattern match isn't bad either, especially for longer blocks of code. For short ones, the overhead of the match starts getting in the way of the point. For example:
op.fold{ printError }{ saveUserInput }
has a lot less syntactic overhead than
op match {
case Some(x) => saveUserInput(x)
case None => printError
}
and therefore, once you expect it, is a lot easier to comprehend.
I'd recommend to simply and safely use opt.get which itself throws a NoSuchElementException exception if opt is None. Or if you want to throw your own exception, you can do this:
val x = opt.getOrElse(throw new Exception("Your error message"))
// x is of type T
as #missingfaktor says, you are in the exact scenario where pattern matching is giving the most readable results.
If Option has a value you want to do something, if not you want to do something else.
While there are various ways to use map and other functional constructs on Option types, they are generally useful when:
you want to use the Some case and ignore the None case e.g. in your case
opt.map(writeToFile(_)) //(...if None just do nothing)
or you want to chain the operations on more than one option and give a result only when all of them are Some. For instance, one way of doing this is:
val concatThreeOptions =
for {
n1 <- opt1
n2 <- opt2
n3 <- opt3
} yield n1 + n2 + n3 // this will be None if any of the three is None
// we will either write them all to a file or none of them
but none of these seem to be your case
Pattern matching is the best choice here.
However, if you want to treat Option as a sequence and to map over it, you can do it, because Unit is a value:
opt map { v =>
println(v) // process v (result type is Unit)
} getOrElse {
println("error")
}
By the way, printing an error is some kind of "anti-pattern", so it's better to throw an exception anyway:
opt.getOrElse(throw new SomeException)

Scala pattern matching case is skipped

Thanks for the excellent example, I tried it and it works as I expected. Nice to see someone understood the nature of the problem. However, I think I should have tagged the problem with Lift as I'm using the Lift framework and that is where this problem is (still) occurring (although I still think it might be related to extraction in scala). Since I don't want to reproduce the entire Lift setup here as it will be too much code, I'm going to hope someone familiar with Lift can understand what I'm doing here. I've removed more variables so it might be easier (for some) to see the problem:
lazy val dispatch: LiftRules.DispatchPF = {
// Explicitly setting guard to false to trigger the scenario
case req: Req if false => () => println("shouldn't match"); Empty
// This should match since previous case will never match
case Req(_, _, _) => () => println("should match"); Empty
// This is actually called...
case _ => () => println("shouldn't reach here"); Empty
}
As before, if I comment out the first case the second case is matched as expected.
For those interested, a simple workaround is:
lazy val dispatch: LiftRules.DispatchPF = {
case req: Req => {
if (false) { // Obviously you put something more useful than false here...
() => println("shouldn't match"); Empty
} else req match {
// This matches
case Req(_, _, _) => () => println("should match"); Empty
// This is now never called
case other => () => println("shouldn't reach here"); Empty
}
}
}
ORIGINAL POST
I'm new to scala, so I may be doing something wrong here, but I have a pattern matching expression that seems to be skipped over. Here's the code:
lazy val dispatch: LiftRules.DispatchPF = {
// Explicitly setting guard to false to trigger the scenario
case req: Req if false => () => Full(...)
// This should match since previous case will never match
case Req("api" :: "test" :: Nil, suffix, GetRequest) => () => Full(...)
// This is actually called...
case _ => () => println("not sure what's going on"); Empty
}
If I take out the first case expression, everything works as expected. I'm tempted to think this is a bug (https://issues.scala-lang.org/browse/SI-2337), but does anyone know of a workaround?
At the very least, change the last line:
case other => () => { println("not sure what's going on " + other); Empty }
and tell us what it prints
I just typed up an example which seems to be the same scenario you've got in your code, and it works as expected in Scala 2.9:
case class Foo(x:String)
val bar = Foo("bar")
bar match {
case x:Foo if false => println("Impossible")
case Foo(x) => println("Expected: " + x)
case _ => println("Should not happen")
}
Which outputs Expected: bar
See if you can reproduce the bug in a self-contained example like this, so maybe we (or if it is a bug, the Scala Dev Team, can figure out what is going wrong :)
Note: Seems like I misread your question the first time, sorry for that. I'm not going to delete this part anyway, because it might be helpful to someone else.
When using pattern matching, the first case-statement that matches will be executed, and after that, the match is complete and all other case statements will be ignored!
Your problem here is, that the first statement
case req:Req =>
matches every instance of Req. After matching the first statement and executing its code, Scala just jumps out of the match expression because it is finished. The second case-statement would match, but it is never executed for any given instance of Req because the first one matches. As far as I remember, this is known as shadowing a case statement.
So move your second case statement before the first one, and you should be fine.
Note that this is why in pattern matching, the more specific match cases need to come first and the more general case statements have to go last.
This is indeed the bug you are referencing in the Scala bug tracker. Req is a non-case class with a companion extractor methods, so the bug manifests itself here. The workaround you introduced seems fine.
For those interested, here is a sample case where the bug manifests itself:
class Sample(val a: String)
object Sample {
def apply(a: String) = new Sample(a)
def unapply(s: Sample) = Option(s.a)
}
val s = new Sample("a")
val r = s match {
case n: Sample if false => "Wrong 1: " + n
case Sample(_) => "Yay"
case n => "Wrong 2: " + n
}
println("Found " + r)
assert(r == "Yay")

Idiomatic way to find a matching line in Scala

I have an Iterable[String] representing the lines in a file and I'd like to find the first line in that sequence that matches a regular expression and return a numerical value extracted by the regex. The file is big enough that it wouldn't make sense to load the whole thing into memory and then call toString() or something, so I'll need to go through it a line at a time.
Here's what I have (it works):
val RateRegex : Regex = ".....".r
def getRate(source : Source) : Option[Double] = {
import java.lang.Double._
for(line <- source.getLines() ) {
line match {
case RateRegex(rawRate) => return Some(parseDouble(rawRate))
case None => ()
}
}
return None
}
This seems ugly to me. It feels very imperative and case None => () might as well be replaced with a comment that says "you're doing it wrong."
I think I want something like def findFirstWhereNonNone(p : Function[A,Option[B]]) => Option[B] where the collection's elements are of type A.
Are there built-in methods that would let me do this in a more functional way? Should I just write that method?
P.S. While I'm at it, is there an alternative to using java.lang.Double.parseDouble? Scala's Double class doesn't expose it.
P.P.S I've seen a lot of posts on SO suggesting that the Source API shouldn't be used in production, but they're all from 2008 and 2009. Is that still the case? If so, what should I use for IO?
Update
I now have:
import util.matching.Regex.Groups
for{line <- source.getLines()
Groups(rawRate) <- RateRegex.findFirstMatchIn(line)} {
return Some(parseDouble(rawRate))
}
return None
which feels a lot better to me.
EDIT: This third alternative ia quite neat:
source
.getLines()
.collectFirst{ case RateRegex(x) => x.toDouble}
Not sure if it's more functional, but you can use the behaviour of foreach/for-comprehensions on Options
def getRate(source : Source) : Option[Double] = {
for {line <- source.getLines()
rawRate <- RateRegex.findFirstIn(line)}
return Some(rawRate toDouble)
return None
}
This works too (quite similar to EasyAngel's answer):
source
.getLines()
.map{RateRegex.findFirstMatchIn(_)}
.filter{_.isDefined}
.map{_.get.group(0).toDouble}
.head
.toList
.headOption
The last three are a little ugly. The take(1) is to ensure we only evaluate up to the first match. The toList is to force the evaluation, and the headOption to extract the first value as Some() or None if there is none. Is there a more idiomatic way of doing this?
Here is one of the possible solutions:
def getRates(source : Source) = source.getLines.map {
case RateRegex(rate) => Some(rate toDouble)
case _ => None
} filter (_ isDefined) toList
Please note, that this function now returns now List[Option[Double]] of all found rates. It's also important, that Iterator remains lazy until I call toList
Update
As was asked in comments, here is solution, that returns only first occurrence:
def getRate(source : Source): Option[Double] = source.getLines.map {
case RateRegex(rate) => Some(rate toDouble)
case _ => None
} find (_ isDefined) getOrElse None