pattern match on a list to check empty - scala

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.

Related

Scala debug this recursive example

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?

How to assign a name to intermediate pattern of a List?

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.

What is the meaning of case in match pattern in scala?

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).

Unreachable code in scala?

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.

Missing parameter type error by calling toSet?

Trying to generate, from a list of chars, a list of unique chars mapped to their frequency - e.g. something like:
List('a','b','a') -> List(('a',2), ('b',1))
So, just mucking around in the console, this works:
val l = List('a', 'b', 'c', 'b', 'c', 'a')
val s = l.toSet
s.map(i => (i, l.filter(x => x == i).size))
but, shortening by just combining the last 2 lines doesn't?
l.toSet.map(i => (i, l.filter(x => x == i).size))
gives the error "missing parameter type".
Can someone explain why Scala complains about this syntax?
When you say val s = l.toSet the compiler figures that the only sensible type for toSet is Char--that's the most specific choice. Then, given that s is a set of Char, the compiler realizes that the map must be from a Char.
But in the second case, it withholds judgment on what the type of elements in toSet is. It might be Char, but AnyVal would also work, as would Any.
l.toSet.map((i: Any) => (i, l.filter(x => x == i).size))
Normally the rule is that the compiler should pick the most specific value. But since functions are contravariant in their argument, they are most specific when they take an Any as an argument, so the compiler can't decide. There could exist a rule to break the tie ("prefer the early assumption"), but there isn't one implemented. So it asks for your help.
You can provide the type either on the function argument or on the toSet to fix the problem:
l.toSet.map((i: Char) => (i, l.filter(x => x == i).size))
l.toSet[Char].map(i => (i, l.filter(x => x == i).size))
Adding the type [Char] to toSet does the trick.
scala> l.toSet[Char].map(i => (i, l.filter(x => x == i).size))
scala.collection.immutable.Set[(Char, Int)] = Set((a,2), (b,2), (c,2))