Scala: pattern matching Option with case classes and code blocks - scala

I'm starting to learn the great Scala language ang have a question about "deep" pattern matching
I have a simple Request class:
case class Request(method: String, path: String, version: String) {}
And a function, that tries to match an request instance and build a corresponding response:
def guessResponse(requestOrNone: Option[Request]): Response = {
requestOrNone match {
case Some(Request("GET", path, _)) => Response.streamFromPath(path)
case Some(Request(_, _, _)) => new Response(405, "Method Not Allowed", requestOrNone.get)
case None => new Response(400, "Bad Request")
}
}
See, I use requestOrNone.get inside case statement to get the action Request object. Is it type safe, since case statement matched? I find it a bit of ugly. Is it a way to "unwrap" the Request object from Some, but still be able to match Request class fields?
What if I want a complex calculation inside a case with local variables, etc... Can I use {} blocks after case statements? I use IntelliJ Idea with official Scala plugin and it highlights my brackets, suggesting to remove them.
If that is possible, is it good practice to enclose matches in matches?
... match {
case Some(Request("GET", path, _)) => {
var stream = this.getStream(path)
stream match {
case Some(InputStream) => Response.stream(stream.get)
case None => new Response(404, "Not Found)
}
}
}

For the first part of your question, you can name the value you match against with # :
scala> case class A(i: Int)
defined class A
scala> Option(A(1)) match {
| case None => A(0)
| case Some(a # A(_)) => a
| }
res0: A = A(1)
From the Scala Specifications (8.1.3 : Pattern Binders) :
A pattern binder x#p consists of a pattern variable x and a pattern p.
The type of the variable x is the static type T of the pattern p. This
pattern matches any value v matched by the pattern p, provided the
run-time type of v is also an instance of T , and it binds the
variable name to that value.
However, you do not need to in your example: since you're not matching against anything about the Request but just its presence, you could do :
case Some(req) => new Response(405, "Method Not Allowed", req)
For the second part, you can nest matches. The reason Intellij suggests removing the braces is that they are unnecessary : the keyword case is enough to know that the previous case is done.
As to whether it is a good practice, that obviously depends on the situation, but I would probably try to refactor the code into smaller blocks.

You can rewrite the pattern as following (with alias).
case Some(req # Request(_, _, _)) => new Response(405, "Method Not Allowed", req)
You cannot use code block in pattern, only guard (if ...).
There are pattern matching compiler plugin like rich pattern matching.

Related

Selector of pattern match being exhaustive

Looking at the Scala doc for sealed classes, it says:
If the selector of a pattern match is an instance of a sealed class, the compilation of pattern matching can emit warnings which diagnose that a given set of patterns is not exhaustive, i.e. that there is a possibility of a MatchError being raised at run-time.
I don't quite understand what they meant in this paragraph. My understanding is that if a switch case, doesn't cover all the possibilities, then we'll get a warning at compile time, saying we might get an error at run time. Is this correct?
I find it strange, because how can we cover ALL the scenarios in a switch case? We would have to match all possible strings, which is just silly, so I take it my understanding is incorrect. Someone care to elucidate, please?
What the paragraph is saying is that in-case you have a fixed hierarchy structure like this:
sealed trait Foo
class Bar extends Foo
class Baz extends Foo
class Zab extends Foo
Then when you pattern match on it, the compiler can infer if you've attempted to match on all possible types extending the sealed trait, in this example:
def f(foo: Foo) = foo match {
| case _: Bar => println("bar")
| case _: Baz => println("baz")
| }
<console>:13: warning: match may not be exhaustive.
It would fail on the following input: Zab()
def f(foo: Foo) = foo match {
^
f: (foo: Foo)Unit
Note the beginning of the document says:
A sealed class may not be directly inherited, except if the inheriting
template is defined in the same source file as the inherited class.
This is unique to Scala, and can't be done in Java. A final class in Java cannot be inherited even if declared inside the same file. This is why this logic won't work for String in Scala, which is an alias for java.lang.String. The compiler warning may only be emitted for Scala types that match the above criteria.
I find it strange, because how can we cover ALL the scenarios in a switch case? We would have to match all possible strings
Yes, if the selector has type String (except it isn't a sealed class, because that's a Scala concept and String is a Java class).
which is just silly
No. For strings, you just need a catch-all case, e.g.
val x: String = ...
x match {
case "a" => ...
case "b" => ...
case _ => ...
}
is an exhaustive match: whatever x is, it matches one of the cases. More usefully, you can have:
val x: Option[A] = ...
x match {
case Some(y) => ...
case None => ...
}
and the compiler will be aware the match is exhaustive even without a catch-all case.
The wildcard character allows us to cover all the scenarios.
something match {
case one => ...
case two => ...
case _ => ...
}
It is selected whenever all other cases don't match; that is, it is the default case. Further information here.

Difference between position of 'if's in pattern matching

Is there a difference between the following two ways of pattern matching:
foo match {
case a if(cond) => println("bar")
case a => println("baz")
case _ => println("default")
}
and
foo match {
case a => if (cond) println("bar") else println("baz")
case _ => println("default")
}
In terms of what you are trying to accomplish, there is no difference. But semantically there is a difference in what you're actually doing.
In the first case, you have a pattern with a guard suffix (the condition). The guard is evaluated only if the pattern in the case matches. If the guard expression evaluates to true, the pattern match succeeds.
In the second case, when the pattern in the case matches, a partial function is executed. Within that partial function body is a condition, and this works out like any function body with a condition inside.
Check out Section 8.4 of the Scala Language Specification for details on pattern matching. It is riveting.
Finally, note both your examples will produce errors or warnings (depending on Scala version) because the defaults are unreachable. I know it is just a contrived example, but just sayin'.
8.4 of the spec says evaluation of expressions may not be in textual order, which is why guards should not be side-effecting.
So if your conditional test is side-effecting, don't put it in a guard.

How to pattern match multiple values in Scala?

Let's say I want to handle multiple return values from a remote service using the same code. I don't know how to express this in Scala:
code match {
case "1" => // Whatever
case "2" => // Same whatever
case "3" => // Ah, something different
}
I know I can use Extract Method and call that, but there's still repetition in the call. If I were using Ruby, I'd write it like this:
case code
when "1", "2"
# Whatever
when "3"
# Ah, something different
end
Note that I simplified the example, thus I don't want to pattern match on regular expressions or some such. The match values are actually complex values.
You can do:
code match {
case "1" | "2" => // whatever
case "3" =>
}
Note that you cannot bind parts of the pattern to names - you can't do this currently:
code match {
case Left(x) | Right(x) =>
case null =>
}
The other answer correctly says that currently there is no way to pattern-match multiple alternatives while extracting values at the same time.
I'd like to share a coding pattern with you that comes close to doing this.
Scala allows you to pattern-match alternatives without extracting values, e.g. case Dog(_, _) | Cat(_, _) => ... is legal. Using this, you can simply extract the values yourself within the case block.
Here's a somewhat contrived example:
abstract class Animal
case class Dog(age: Int, barkLevel: Int) extends Animal
case class Cat(apparentAge: Int, cutenessLevel: Int) extends Animal
val pet: Animal = Dog(42, 100)
// Assume foo needs to treat the age of dogs and the apparent age
// of cats the same way.
// Same holds for bark and cuteness level.
def foo(pet: Animal): Unit = pet match {
case animal#(Dog(_, _) | Cat(_, _)) =>
// #unchecked suppresses the Scala warning about possibly
// non-exhaustiveness even though this match is exhaustive
val (agelike, level) = (animal: #unchecked) match {
case Dog(age, barkLevel) => (age, barkLevel)
case Cat(apparentAge, cutenessLevel) => (apparentAge, cutenessLevel)
}
???
}
Assume that ??? actually stands for doing something that is equal for dogs and cats. Without this coding pattern, you would need to have two cases, one for dogs and one for cats, forcing you to duplicate code or at least to outsorce code into a function.
Generally, the coding pattern above is suitable if you have sibling case classes that share fields that behave identically only for some algorithms. In those cases, you cannot extract those fields to a common superclass. Still, you would like to pattern-match in a uniform way on those fields in the algorithms that treat them equally. This you can do as shown above.

How can I easily define more complex PartialFunctions in Scala?

PartialFunctions
In Scala, a PartialFunction is, in short, a function that additionally defines an isDefinedAt method.
It is easy to define partial functions with a series of case statement. A trivial example would be, e.g.:
scala> val pf: PartialFunction[Int, Unit] = {
| case 42 => ()
| }
pf: PartialFunction[Int,Unit] = <function1>
scala> pf.isDefinedAt(42)
res0: Boolean = true
scala> pf.isDefinedAt(0)
res1: Boolean = false
isDefinedAt is automatically generated from the list of cases defining the partial function.
Context
The Lift framework makes use of partial functions in many places, e.g. to define whether a request should be processed by Lift's engine or served directly from a file on disk, as is. and sometimes, I find myself wanting to write a case statement that matches all input parameters and only later decide if I want to return a value or not. This means that the initial series of cases is not enough any more to determine if my function is defined at a given value or not
For instance, in Lift, I want to add a rule that all html and htm files are served directly, and that files with the “lift” extension should be processed. It would look easy to do something like this:
LiftRules.liftRequest.prepend {
case Req(path, extension, tpe) => extension match {
case "html" | "htm" => false
case "lift" => true
}
}
Unfortunately, in this case, the compiler thinks that my partial function is defined everywhere, as the first case always matches. It's the nested match that may not match all incoming requests. And, is a request is not matched, a MatchError is thrown.
Question
Is there a simple way to make the compiler consider nested match statements when defining a partial function, or is the only way to do it to inline all nested conditionals like this?
LiftRules.liftRequest.prepend {
case Req(path, extension, tpe) if extension == "html" || extension == "htm" => false
case Req(path, extension, tpe) if extension == "lift" => true
}
In this example, it's largely doable, but the readability is decreased, and I've faced cases where inlining all checks looks very ugly.
In this case, you may want to write
LiftRules.liftRequest.prepend {
case Req(path, "html" | "htm", tpe) => false
case Req(path, "lift", tpe) => true
}
For more complicated cases, you’ll need to define your own extractor which you’ll have to use instead of a nested case statement.
object CheckExtension {
def unapply(ext: String) = ext match {
case "lift" => Some(true)
case "html" | "htm" => Some(false)
case _ => None
}
}
LiftRules.liftRequest.prepend {
case Req(path, CheckExtension(valid), tpe) => valid
}
This will only match if your predefined unapply function returns Some and assign the value of Some to the free variable valid. If unapply returns None, no match is being generated.

Need clarification on Scala literal identifiers (backticks)

Reading the Programming in Scala 2nd Ed and I came across this:
literal identifier
"The idea is that you can put any string that's accepted by the runtime as an identifier between backtick"
I'm not entirely sure why I would use this? The book gave a use case of accessing the static yield method in Java's Thread class.
So since in Scala, yield is a reserve word, if I use yield with backticks,
Thread.`yield`()
it would ignore the Scala's yield and let me access the Java's Thread class's method yield instead?
Thank you in advance.
Exactly. Using backticks, you can more or less give any name to a field identifier. In fact, you can even say
val ` ` = 0
which defines a variable with name (one character of whitespace).
The literal definition of identifiers is useful in two cases. The first case is, when there is already a reserved word of the same name in Scala and you need to use a Java library which does not care about that (and of course, why should it).
The other use case comes with case statements. The convention is that lower case names refer to match variables, whereas upper case names refer to identifiers from the outer scope. So,
val A = "a"
val b = "b"
"a" match {
case b => println("b")
case A => println("A")
}
prints "b" (if the compiler were dumb enough not to fail with saying case A were unreachable). If you want to refer to the originally defined val b, you need to use backticks as a marker.
"a" match {
case `b` => println("b")
case A => println("A")
}
Which prints "A".
Add There is a more advanced use case in this recent question method with angle brackets (<>) where the backticks were needed to get the compiler to digesting the code for a setter method (which in itself uses some ‘magic’ syntax).
Thank you #Debilski, it helps me to understand this code below from AKKA doc :
class WatchActor extends Actor {
val child = context.actorOf(Props.empty, "child")
...
def receive = {
...
case Terminated(`child`) ⇒ ...
}
}
The case :
case Terminated(`child`)
matches a message of type Terminated with ActorRef field equals to child which is defined earlier.
With this statement :
case Terminated(c)
We match every Terminated messages with any reference of ActorRef mapped in c.