Scala - Pattern Matching for particular fields on a case class? - scala

Let's say I have a case class like this
case class CompanyInput(maybeField1: Option[field1], maybeField2: Option[field2], maybeField3: Option[field3], maybeUserTimeZoneId: Option[ZoneId], capabilities: Vector[CompanyCapability])
And I want to check that maybeField1 , maybeField2 and maybeField3 are set and optional.... Changing the fields from option to not option is not possible.

You can use type-specific patterns to compose a bigger pattern and also mark fields irrelevant for a particular branch as underscores
val companyInput = ???
companyInput match {
case CompanyInput(Some(field1), Some(field2), Some(field3), _, _) => ???
}

Related

Scala: using wildcard with Option in pattern matching for a case class with too many parameters

I have a pattern matching code. X is a case class with too many parameters. I just want to do some check for its 3rd,4th parameter, and would like to use wildcard for rest of them.
o match {
case Some(X(_,_, a,b, _*))) => // do something
case _ => // do something else
}
This doesn't seem to work for me. What is correct way of using wildcard here?

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.

Scala: pattern matching Option with case classes and code blocks

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.

create type from pattern matching in scala

I'm new using Scala and what I need is to create like a dynamic type based on some pattern matching function, like
type defType = "value1" match {
case "value0" => typeOf[String]
case "value1" => typeOf[Integer]
case _ => typeOf[Double]
}
val test5 : defType = 4
This is just an example given that I'd to work with more complex structures, but gives the idea of what I want to do.
I probably don't understand what you're doing, but this seems problematic to me:
val test5 : defType = 4
The compiler needs to be able to know defType at compile time, otherwise it can't type check. Based on that, I think what you want to do is do this pattern matching at compile time by utilizing Scala macros.
However, I have a feeling that's not the right solution either just because this whole scenario seems very strange. If you give more detail about what the bigger picture is of what you're trying to do maybe we can suggest a better solution.
I fear this is not possible, for fundamental conceptual reasons. As type rules are checked at compile time, it is not possible to derive types based on values that might be unknown until runtime.
That being said, you might be able to tackle your design problem by defining a family of case classes, each being a wrapper for a value of a specific type. By giving these classes a common base class, you can store a value of any type you wish into the same variable and extract it through type-safe pattern matching:
class Base
case class AString(val value: String) extends Base
case class AnInt(val value: Int) extends Base
case class ADouble(val value: Double) extends Base
val a : Base = "value1" match {
case "value0" => AString(…)
case "value1" => AnInt(…)
case "value0" => ADouble(…)
}
a match {
case AString(s) => …
case AnInt(i) => …
case ADouble(i) => …
…
}

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.