How to suppress "match is not exhaustive!" warning in Scala - scala

How can I suppress the "match is not exhaustive!" warning in the following Scala code?
val l = "1" :: "2" :: Nil
l.sliding(2).foreach{case List(a,b) => }
The only solution that I found so far is to surround the pattern matching with an additional match statement:
l.sliding(2).foreach{x => (x: #unchecked) match {case List(a,b) => }}
However this makes the code unnecessarily complex and pretty unreadable. So there must be a shorter and more readable alternative. Does someone know one?
Edit
I forgot to mention that my list l has at least 2 elements in my program. That's why I can safely suppress the warning.

Here are several options:
You can match against Seq instead of List, since Seq doesn't have the exhaustiveness checking (this will fail, like your original, on one element lists):
l.sliding(2).foreach{case Seq(a, b) => ... }
You can use a for comprehension, which will silently discard anything that doesn't match (so it will do nothing on one element lists):
for (List(a, b) <- l.sliding(2)) { ... }
You can use collect, which will also silently discard anything that doesn't match (and where you'll get an iterator back, which you'll have to iterate through if you need to):
l.sliding(2).collect{case List(a,b) => }.toList

Making it complete with ; case _ => ??? is pretty short. ??? just throws an exception. You can define your own if you're using 2.9 or before (it's new in 2.10).
It really is pretty short compared to what you need for a match annotation:
(: #unchecked)
; case _ => ???
^ One more character!
It doesn't throw a MatchError, but does that really matter?

Since your sliding(2) can possibly return one last list with only one element in it, you should also test it:
l sliding(2) foreach {
case a::b::Nil => println("two elements: " + a + b)
case l => println("one last element" + l.head)
}

implicit class RichAny[A](private val a: A) extends AnyVal {
#inline
def match_ignoring_nonexhaustive[B](f: PartialFunction[A,B]): B = f(a)
}
With this you could do the following, which actually only interprets the case match as PartialFunction:
l.sliding(2).foreach{ _ match_ignoring_nonexhaustive {case List(a,b) => }}

Related

Understand Scala match for case classes with two members

I've been working with Scala for a while and it still troubles me a lot. I don't know why they made it so complex. I am trying to understand matching case classes when there are only two members for this case class
def main(args: Array[String]): Unit = {
case class X(a: String, i: Int)
def doSome(x: X): Unit = {
x match {
case "x" X 1 => print("ahhh") // <---- HERE !
case X(_, _) => println("")
}
}
doSome(X("x", 1))
case class Y(a: String, i: Int, j: Int)
def doAnother(y:Y): Unit = {
y match {
case "y" X 1 => print("ahhh") // how to make similar syntax when there are more than one syntax ?
case Y(_, _,_) => println("") // this is understandable
}
}
doAnother(Y("y", 1,2))
}
How can the syntax "x" X 1 match X("x",1) and if "x" X 1 can match match X("x",1) then what matches Y("y",1,2), obviously "y" Y 1 Y 2 doesn't work?
What is so special about the first argument if we can match on "y" Y (1,2)?
At least in case of List it feels more natural to me, for example consider
List(42, 11) match {
case head :: tail =>
case Nil =>
}
as opposed to
List(42, 11) match {
case ::(head, tail) =>
case Nil =>
}
where head :: tail communicates directly the shape of the List.
As a side note, infix notation can sometimes communicate intent more clearly, for example, consider syntax of generalised constraints
implicitly[List[Int] <:< Iterable[Int]] // infix type notation seems more natural
implicitly[<:<[List[Int], Iterable[Int]]]
You don't have to use a language feature just because it is there.
In this case I can see no reason not to use the standard class matching version:
x match {
case X("x", 1) => print("ahhh")
case _ => println("")
}
}
y match {
case Y("y", 1, _) => print("ahhh")
case _ => println("")
}
Ok, so the thing I was looking for is called "Infix Types". From Scala for Impatient, 2nd edition
An infix type is a type with two type parameters, written in “infix”
syntax, with the type name between the type parameters. For example,
you can write String Map Int instead of Map[String, Int] The
infix notation is common in mathematics. For example, A × B = { (a, b)
| a Œ A, b Œ B } is the set of pairs with components of types A and B.
In Scala, this type is written as (A, B). If you prefer the
mathematical notation, you can define type ×[A, B] = (A, B) Then you
can write String × Int instead of (String, Int). All infix type
operators have the same precedence. As with regular operators, they
are left-associative unless their names end in :. For example,
String × Int × Int means ((String, Int), Int). This type is similar
to, but not the same, as (String, Int, Int), which could not be
written in infix form in Scala.
To answer your query on What is so special about the first argument if we can match on "y" Y (1,2)?: this is because of how your case class gets decomposed via its unapply method.
The preferred way of matching against a case class is how you've done in the second statement of both your methods.
However, for Y, the preferred way to match would be case Y("y", 1, 2) as mentioned in Tim's comment.
For X, a few ways you can use power of pattern matching are (similarly for Y):
case X("x", 1) => ???
case X(a, 1) => ???
case X(_, 1) => ???
case X("x", _) => ???
case x#X("x", _) =>
case X(a, b) if b > 5 => ???
The following, however, is a very bad style as it compromises readability and hence maintainability of the code
case "x" X 1 => print("ahhh")
As Mario mentioned, the way you're using pattern matching is more suited for lists instead of case classes, as it makes your code consistent with the way a list is structured (head cons tail), and thus enhances readability.
You can go through following articles for a more deeper understanding on how to exploit the power of scala's pattern matching:
https://www.artima.com/pins1ed/case-classes-and-pattern-matching.html
https://docs.scala-lang.org/tour/pattern-matching.html
https://docs.scala-lang.org/overviews/scala-book/match-expressions.html

How can I remove duplicates from a list in Scala with pattern matching?

As homework i have to write a function that will remove duplicates from a list. It should be recursive and with pattern matching. I am not allowed to use list functions like head,tail,contains,etc... .
For sorted lists i came up with this solution:
def remove(u:List[Int]):List[Int] = {
u match { case Nil => u
case hd::hd2::tl => if(hd == hd2) remove(hd2::tl) else hd :: remove(hd2::tl)
case hd::tl => hd :: remove(tl)
}
}
How can i do it for unsorted lists?
I won't do your homework for you, but hope, this will help.
You want to make your function tail-recursive. That means that the recursive call appears in the very last position of the function, so that the jvm can clear up the previous call from the stack before invoking it (it makes it execute very much like a loop, without requiring additional space on stack). In your original solution it is statements like this, that make it not tail-recursive: hd :: remove(tl): you have to invoke the recursive call, and then prepend hd to its result. The then part breaks the idea of tail recursion, because jvm has to remember on stack the place to return to after the recursive call is finished.
This is typically avoided by carrying the final result of the function through the recursion as an argument:
def remove(u: List[Int], result: List[Int] = Nil): List[Int] = u match {
case Nil => result
case a :: b :: tail if a == b => remove(b :: tail, result)
case head :: tail => remove(tail, head :: result)
}
(Note, that both recursive invocations here are in the tail position - there is nothing left to do after the call returns, so the previous entry can be cleared from the stack prior to invoking the recursion).
You need another recursive function - contains - that tells whether a given element is contained in a list. Once you have that, just replace the second case clause above with something like
case head :: tail if contains(head, result) => remove(tail, result)
and your job is done!
If you want to preserve the original order of elements of the list, you will need to reverse it afterwards (replace case Nil => result with case Nil => result.reverse) ... If you are not allowed to use .reverse here too, that's going to be another nice exercise for you. How do you reverse a list (tail-)recursively?
I would probably go about sorting the list firstly so that we can apply the O(n) complexity pattern matching method but in order to keep the order you will need to index the list so that you can recover the order later, this can be done with the zipWithIndex method. And also since the data type changes from List[Int] to List[(Int, Int)], you will need to define another recursive remove function inside the original one:
def remove(u: List[Int]): List[Int] = {
val sortedU = u.zipWithIndex.sortBy{ case (x, y) => x}
def removeRec(su: List[(Int, Int)]): List[(Int, Int)] = {
su match {
case Nil => su
case hd :: Nil => su
case hd :: hd2 :: tail => {
if (hd._1 == hd2._1) removeRec(hd2 :: tail)
else hd :: removeRec(hd2 :: tail)
}
}
}
removeRec(sortedU).sortBy{case (x, y) => y}.map{ case (x, y) => x}
}
val lst = List(1,2,3,1,3,3)
remove(lst)
// res51: List[Int] = List(2, 1, 3)
Note: This follows OP's pattern and is not tail-recursive. And if you want a tail recursive version, you can follow #Dima's nice explanation.

how to implement deep reverse of different type sequence inscala

If I have a Vector of different type number,say, Vector("abcde",Vector(1,2,3),List(4,5,6),7), and I want to get a function:deep_reverse to reverse the vector deeply to Vector(7,List(6,5,4),Vector(3,2,1),"edcba"), I want something like:
def reverse2(xs:Seq[Any]):Seq[Any] = xs match{
case Seq() => Seq()
case a +: ys=> a match{
case _:Seq[Any] =>reverse2(ys) ++: reverse2(a)
case _:Int =>reverse2(ys) ++: Seq(a)
}
but I can't pass the compiler, how to correct my code? Thanks a lot!
First off, this is really scary code because you should never use Any. The whole point of type safety is to know the types of your data and allow the code to be guaranteed to work with them. This code throws away any of the benefits of using a typed language, and is really unsafe. What happens if your Seq contains an Array? Or a Double? Or a user-defined class? How should those be reversed?
That said, you're making things more complicated than they need to be. Instead of doing your recursive approach through matching, just reverse the main list and then map over each element.
def reverse2(xs: Seq[Any]): Seq[Any] = {
xs.reverse.map {
case i: Int => i
case s: String => s.reverse
case s: Seq[Any] => reverse2(s)
}
}
By the way: your compile error is due to the fact that a isn't known to be a Seq[Any] when you call reverse2(a). You need do something like case b: Seq[Any] => ... reverse2(b).
Even if you fixed that you'd still get a runtime error since you're not handling String.
You were very close :)
def reverse2(xs:Seq[Any]):Seq[Any] = xs match{
case Seq() => Seq()
case a +: ys=> a match{
case x:Seq[Any] =>reverse2(ys) ++: reverse2(x)
case y:Int =>reverse2(ys) ++: Seq(y)
}
}

Scala: where to put the #unchecked annotation in a foreach

I have the following:
samples.sliding(2).foreach{case List(a, b)=> printf("%x %x\n", a.value, b.value)}
I know that the single 'case' will match all the possible values but I get a 'match is not exhaustive' warning. The Scala book explains where to put the #unchecked annotation on a normal fully-specified match expression, but not for the form above. How do I annotate the above to stop the compiler from complaining?
#unchecked is only defined for the selector in a match operation, not for arbitrary functions. So you could
foreach{ x => (x: #unchecked) => x match { case List(a,b) => ... } }
but that is rather a mouthful.
Alternatively, you could create a method that unsafely converts a partial function to a complete one (which actually just casts to the function superclass of PartialFunction):
def checkless[A,B](pf: PartialFunction[A,B]): A => B = pf: A => B
and then you can
samples.sliding(2).foreach(checkless{
case List(a,b) => printf("%x %x\n", a.value, b.value)
})
and you don't have any warnings because it was expecting a partial function.
No idea about #unchecked, but why not just call x.head and x.tail.head or x(0) and x(1)?
Why don't you add an dummy case, if you're sure it will never happen?
samples.sliding (2).foreach {
case List (a, b) => printf ("%x %x\n", a.value, b.value)
case _ => sys.error ("impossible")
}

Scala collectFirst with function returning Option[U]

I've had this situation occur a number of times in the library I'm writing, and I'm not particularly satisfied with the solutions I've come up with so far.
Let's say that I have an expensive function f that takes an item of type T and returns a value of type Option[U]. Now, suppose I have a collection of type T and I want to retrieve the first non-None value returned by f when performed across the elements of T without evaluating f for all elements of T if the value has already been found.
The only way I've come up with to do this is to wrap F into an Extractor Object, and use it with scala's collectFirst method.
For example:
object FMatch { def unapply(t : T) = f(t) }
collection.collectFirst{ case FMatch(result) => result }
This seems a little inelegant, and I'm not certain whether f is evaluated only once or twice for each result (I haven't tested this to find out yet). It seems like it would be useful to have a version of collectFirst that takes a parameter of type T => Option[U] instead of a PartialFunction1[T].
Is there a more elegant way to do this that I'm missing?
Use a view over the collection, to make it lazy and defer invocation of that function until the last possible moment (e.g. it won't be called at all for elements beyond the first match):
xs.view map {f(_)} collectFirst {case Some(x) => x}
or
xs.view map {f(_)} find {_.isDefined}
or in the point-free style, as per Alexey's response:
xs.view map {f} find {_.isDefined}
That should hopefully give you a couple of alternative ways to think about the problem more generally :)
Use this:
collection.toIterator.map(f).find(_.isDefined)
#annotation.tailrec
def first[A, B](as: Traversable[A], f: A => Option[B]): Option[B] =
if (as.isEmpty) None
else f(as.head) match {
case s # Some(_) => s
case _ => first(as.tail, f)
}
Give a partial functions to collectFirst
collectionT
.collectFirst { t =>
f(t) match {
case Some(u) => u
}