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).
Related
I want to check if a list is empty using pattern matching
val simplelist: List[Char] = List('a', 'b', 'c', 'd')
def test(l:List[Char]):Unit= l.map(d => print(d))
simplelist match {
case x :: xs =>
test(xs)
case Nil=> log.info("empty")
}
Output is bcd and not abcd
You could try it as simple as:
scala> List(1,2).isEmpty
res0: Boolean = false
You do not need pattern matching for this.
For Empty List pattern match, you can do this.
val simplelist: List[Char] = List('a', 'b', 'c', 'd')
def test(l:List[Char]):Unit= l.map(d => print(d))
simplelist match {
case x :: xs =>
test(xs)
case List() => println("empty List") // this will pattern match as empty List
case Nil=> log.info("empty")
}
2) For the question, Output is bcd and not abcd
In case x :: xs, List('a', 'b', 'c', 'd') matches as
x = 'a' and
xs = List('b', 'c', 'd')
And you are passing only xs to test method. Hence it is printing only b,c,d as expected.
In the match expression, "x :: xs" matches Lists with a first element, which will be stored as "x", and a tail which will be stored as "xs". Then, you print the contents of "xs", so are passing only the tail of the list to test. It will match any list with a head element and a tail, including a -> Nil, a list of one element. In that example, "a" will be stored in x, and Nil will be stored in xs.
This will work if you try:
simplelist match {
case Nil => log.info("empty")
case x => test(x)
}
This will try to match the empty list, then match anything else and refer to it as x, and print the results. Because simplelist is definitely a List (and assuming you did not use null), the x will refer to a non-empty list, and you can call test(x).
It would also work to do
simplelist match {
case x :: xs => test (simplelist)
case Nil => log.info("empty")
}
which would match any list with a first element and a tail, but then pass simplelist to test.
def append[T](xs: List[T], ys: List[T]): List[T] =
println(xs)
xs match {
case List() => ys
case x :: xs1 => x :: append(xs1, ys)
}
append(List(1,2), List(3,4));
So the println(xs) code won't run.I basically want to see what hapepns when xs1 is just a single element array. But how can I do this? I basically want to see if this is single element list is deconstructed into the single element and xs1 is like null or [] on the next pass.
What debuggers does Scala have? How can I use them? Why doesn't println(xs) work?
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.
Here's my attempt of the 3rd problem (P03) of the 99 Problems in Scala (http://aperiodic.net/phil/scala/s-99/):
import scala.annotation._
// Find the nth element of a list.
// nth(2, List(1, 1, 2, 3, 5, 8)) = 2
object P03 {
#tailrec def nth[A](n: Int, ls: List[A]): A = (n, ls) match {
case (0, h :: t :: Nil) => h
case (n, _ :: t) => nth(n - 1, t)
case _ => println(n); throw new IllegalArgumentException
}
The enigma is that this code prints -4 and throws an IllegalArgumentException
The solution of course is to change the first pattern to:
case (0, h :: _) => h
This now prints the correct answer 2
Question is Why? What is the subtle difference between:
case (0, h :: t :: Nil) => h
&
case (0, h :: _) => h
Thanks!
The difference is that h :: t :: Nil matches only a list with two elements (h and t, Nil is the marker for the end of a list (I'm not 100% sure it's the exact nomenclature)) while h :: _ matches every non empty list, ie a list that has at least one element, if you check the :: class you'll see:
final case class ::[B](private var hd: B, private[scala] var tl: List[B]) extends List[B]
Which has a head and a tail where the first is the first element of the list and the second is the rest, matching on h :: t :: Nil means getting the first element of the list, than the first of the tail and then there should be a Nil, matching on h :: _ means getting the head and then you don't care of what's left as long as there's a head.
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.