For some reason the following code is unreachable. I cannot understand why my code will never get reached as this is a simple pattern matching. Here it is:
type Occurrences = List[(Char, Int)]
def combinations(occurrences: Occurrences): List[Occurrences] = occurrences match{
case Nil => Nil
case List() => List()
case x => List(x)
case x::xs => combinations(List((x._1,x._2 - 1))) ::: combinations(xs)
}
This algorithm is meant to extract all of the sub lists of the given list.
case x => List(x) matches anything. It looks like you want to match a 1-element list so you can use:
case l#List(_) => List(l)
scala> Nil == List()
res0: Boolean = true
What did you expect what List() is?
Btw, the error message does exactly tell you what the problem is:
scala> def combinations(occurrences: Occurrences): List[Occurrences] = occurrences match{
| case Nil => Nil
| case List() => List()
| case x => List(x)
| case x::xs => combinations(List((x._1,x._2 - 1))) ::: combinations(xs)
| }
<console>:11: warning: patterns after a variable pattern cannot match (SLS 8.1.1)
case x => List(x)
^
<console>:12: warning: unreachable code due to variable pattern 'x' on line 11
case x::xs => combinations(List((x._1,x._2 - 1))) ::: combinations(xs)
^
<console>:12: warning: unreachable code
case x::xs => combinations(List((x._1,x._2 - 1))) ::: combinations(xs)
^
combinations: (occurrences: Occurrences)List[Occurrences]
I am a Scala newbie, and I ran into a similar problem, and was confused by the warning the compiler gave. Here's what confused me and what my solution was, if others run into the same thing.
My compiler gave me a warning roughly like this (but I'm substituting the OP's code in place of mine):
[warn] path/to/file.scala:123: unreachable code
case x::xs => combinations(List((x._1,x._2 - 1))) ::: combinations(xs)
^
The compiler points to a symbol in your last case statement, where in fact (as others have mentioned) the problem lies in your List() case statement. I at first mistook this to mean there was a problem in the case statement the compiler prints. (In my case, a '::' that I thought I had used incorrectly.)
What the compiler message means is that the statement is unreachable, and has nothing to do with the character it points to. The reason the statement is unreachable, as others have mentioned, is that the List() statement is a catch-all, and the matching won't flow through to the rest of the cases.
To fix this, make sure the logic can flow through to all your cases and doesn't get stuck at a catch-all. i.e. go from most specific to least specific. I was also trying to match a list by the number of elements, and here's my solution [Compiles and works, with no warning!]:
def myFunction(myList: List[MyType]) = myList match {
case x1 :: x2 :: xs => // match 2+ elems
case x :: xs => // match 1+ elems
case Nil => // match 0 elems
However, if I rearrange the first two lines, I get that unreachable code warning again, because the match 2+ case is more specific than the 1+ case [Doesn't work, and unreachable code warning!]:
def myFunction(myList: List[MyType]) = myList match {
case x :: xs => // match 1+ elems
case x1 :: x2 :: xs => // match 2+ elems
case Nil => // match 0 elems
I guess you want to match one single element with case x => List(x). That matches anything.
Use case x :: Nil => List(x) instead.
Related
I'm reading some Scala problems and I see this:
def last[A](l: List[A]): A = l match {
case h :: Nil => h
case _ :: tail => last(tail)
case _ => throw new NoSuchElementException
}
I understand the basics of the cons operator. But where does the h come from?
In that top case h, I can see how we're saying in the event that there is Nil at the end of the list, return h, which would be the last element of the list. But where is h even defined?
The h is defined right there in the case statement.
Scala's pattern matching has pretty concise syntax that can take a beat to get used to. It mixes some stuff that look very similar:
If you include a literal value, the object you're matching on must be equal to that value. Example: case 1 :: tail => ... matches only lists that start with 1.
If you include an _, that matches anything. Example: case _ :: tail => ...
If you include a new variable name, that matches anything, and assigns what it matched to that variable within the scope of the corresponding body. Example: case h :: tail => ... which matches the exact same inputs as the previous example but also assigns the first element to h within the "..." section.
h is an identifier that represents a single element of type A and is defined in the case clause itself: the letter "h" is sensible in this context because it clearly means "head." However, you can use whatever legal Scala identifier you want:
def last[A](l: List[A]): A = l match {
case baconWrappedShrimp :: Nil => baconWrappedShrimp
case _ :: tail => last(tail)
case _ => throw new NoSuchElementException
}
Scala pattern matching allows you to write temp variables in the cases.
The first case covers the case where l is a the following list {h, Nil}. Pay attention that the '::' operator is used to concatanate a single element with a list. Unlike the ':::' operator which concatanates two lists.
So I read about right-associative operators like the cons operator in Scala. I'm wondering why they work in case statements. It seems like you can pattern match using the cons statement here?
def findKth1[A](k:Int, l:List[A]):A = (k, l) match {
case (0, h::_) => h
case(k, _::tail) if k > 0 => findKth1(k - 1, tail)
case _ => throw new NoSuchElementException
}
findKth1(2, List(3,4,5,6))
res1: Int = 5
What is the placeholder doing here? I've only seen placeholders used in functions like this: <SomeList>.map(_.doThing). Is it the same concept?
The only difference with :: and ::: is that ::: is used for 2 Lists right?
tl;dr It isn't pattern matching the operator, it's pattern matching a case class called ::
There are a couple of things happening at the same time. First of all, there may be a bit of confusion, because :: is a method on List:
val x: List[Int] = 1 :: 2 :: 3 :: Nil
But there is also a case class :: that, according to the docs is:
A non empty list characterized by a head and a tail.
More info here
Scala's case classes automatically come with extractor methods(unapply), which allow pattern matching, as in case User(name, age) => ....
You are also allowed to use the case class name in an infix position (although you shouldn't do so, except when the case class is used like an operator, such as in this case). So case head :: tail => ... is the same as case ::(head, tail) => .... More info here
When pattern matching, you can use _ to mean that there will be a value there, but you don't care about it, so you aren't providing it a name.
So the three cases you provided are roughly:
A tuple where the first value is 0, and the second value is a list with a head to be called h, and a tail which we will ignore.
A tuple with some integer to be called k, and a list with a head that we don't care about, and a tail, which we will call tail. Also, k must be greater than 0
Anything else, then throw a NoSuchElementException
This code don't compile, what am I doing wrong? is it possible to do it?
How can I pattern match a list with at least 2 elements, and have the pattern have a variable for the tail (meaning y :: _)
I know it's possible desugaring the :: or with a simple if. But without desugaring and without if... it's possible?
val list:List[Int] = ...
list match {
case x :: tail#(y:: _) =>
}
Try if this code works for you:
list match {
case x :: (tail#(y :: _)) =>
}
You use another variable to hold the second element:
list match {
case x :: y :: _ =>
}
This will only match a list with at least two elements, will bind x to the first element, y to the second element and ignore the rest.
If you need to just ensure the remainder of the list is at least 1 long, then
list match {
case x :: y if y.size > 0 =>
}
will do the job.
val list1 = List(1, 1, 2, 3, 5,7,8,4)
def lastrecursive[A](ls :List[A]):A = ls match{
case p :: Nil => p // what is the meaning of Nil
case _ :: tail => lastrecursive(tail)
case _ => throw new NoSuchElementException
}
For the code ABOVE in recursive format. Can anyone explain why we are giving
:: and case h and case tail and case _. while working on list match pattern.
and for reversing a list
def reverseRecursive[A](ls: List[A]): List[A] = ls match {
case Nil => Nil
case h :: tail => reverseRecursive(tail) ::: List(h)
}
how this ::: List(h) works?
the :: method is used to construct and deconstruct a list. a::b means the head of the list is a (a single element) and the tail is b (a list).
p::Nil means a case where there is some element p and the tail is the empty list (Nil).
This case basically finds the last actual element in the list.
The second case is similar: h::tail means an element h and a list tail. So we reverse the tail and then add the list of h to the end (l1 ::: l2 prepends the list l1 to the list l).
Trying to produce a list of tuples showing prime factor multiplicity... the idea is to match each integer in a sorted list against the first value in a tuple, using the second value to count. Could probably do it more easily with takeWhile, but meh. Unfortunately my solution won't compile:
def primeFactorMultiplicity (primeFactors: List[Int]) = {
primeFactors.foldRight (List[(Int, Int)]()) ((a, b) => (a, b) match {
case (_, Nil) => (a, 1) :: b
case (b.head._1, _) => (a, b.head._2 + 1) :: b.tail
case _ => (a, 1) :: b
})
}
It says "error: stable identifier required, but b.head._1 found." But changing the second case line to the following works fine:
case (i, _) if (i == b.head._1) => (a, b.head._2 + 1) :: b.tail
Why is this, and why can't the compiler cope if there is such a simple fix?
A variable in a pattern captures the value in that position; it does not do a comparison. If the syntax worked at all, the result would be to put the value of a into b.head._1, overwriting the current value. The purpose of this is to let you use a pattern to pull something out of a complex structure.
b.head._1 is not a valid name for the result of the (x, y) tuple extractor
Try this instead:
case (x, _) if x == b.head._1 => (a, b.head._2 + 1) :: b.tail