Why is this matching not allowed in scala? - scala

I have to find if an element is inside a list using scala, and I am only allowed to use recursion. Why is the following code not working, as the match statement seems to be correct to me. My IDE gives me an error on all three case statements and it says type, mistmatch, boolean required.
def isInN(x: Int, l: List[Int]): Boolean = (l,l.head) match {
case Nil,_ => false
case _,x => true
case _,_ => isInN (x,l.tail)
}

You're matching a tuple, so you need to use a proper tuple extractor. i.e. just add parenthesis:
def isInN(x: Int, l: List[Int]): Boolean = (l, l.head) match {
case (Nil, _) => false
case (_, x) => true
case (_, _) => isInN (x, l.tail)
}
This compiles, but won't quite work like you want it to. l.head will throw an exception if the list is empty. And x within the match will eagerly match anything, so the last case can never be reached. To match against an identifier, you need to surround it with backticks, otherwise it will just be a placeholder matcher.
To use a similar pattern match without calling l.head, you can pattern match on the List itself:
def isInN(x: Int, l: List[Int]): Boolean = l match {
case Nil => false
case `x` :: _ => true
case head :: tail => isInN (x, tail)
}
Though this is all trumped by contains in the standard collections library:
scala> List(1, 2, 3, 4).contains(2)
res5: Boolean = true

Related

Scala - head of empty list - removing all None's from a list of Options

Been trying to solve this for a while now. I need a recursive function that removes all None's from a list of Option[Int]'s, without using if-statements or using other functions.
def RemoveNone2(input: List[Option[Int]]) : List[Int] = {
input.head match {
case None => RemoveNone2(input.tail)
case _ => (input.head.get::RemoveNone2(input.tail))
}
}
val optional: List[Option[Int]] = List(Some(13), None, Some(32), None, Some(51), None, Some(17), None)
RemoveNone2(optional)
But when trying to execute the code, I get the following error:
java.util.NoSuchElementException: head of empty list
I suck at Scala, could anyone offer some insight?
You want headOption:
def RemoveNone2(input: List[Option[Int]]) : List[Int] = input.headOption match {
case None => RemoveNone2(input.tail)
case Some(head) => head :: RemoveNone2(input.tail)
}
A better way to write this is:
def removeNone(input: List[Option[Int]]) : List[Int] = input match {
case Nil => Nil
case Some(head) :: tail => head :: removeNone(tail)
case None :: tail => removeNone(tail)
An even better way is to use an accumulator, so that you can take advantage of tail-recursion:
def removeNone(input: List[Option[Int]], out: List[Int]=Nil) : List[Int] = input match {
case Nil => out.reverse
case Some(head) :: tail => removeNone(tail, head :: out)
case None :: tail => removeNone(tail, out)
}
You need to check that input list is empty to break the recursion. One of the options is to match against the list itself:
def RemoveNone2(input: List[Option[Int]]) : List[Int] = input match {
case head :: tail => head match {
case Some(value) => value :: RemoveNone2(tail)
case _ => RemoveNone2(tail)
}
case _ => Nil
}
Also note, that this implementation is not tail-recursive, whcih can lead to errors or poor performance for big collections. Tail-recursive implementation can look like that:
def RemoveNone2(input: List[Option[Int]]) : List[Int] = {
#annotation.tailrec
def inner(innerInput: List[Option[Int]], acc: List[Int]): List[Int] = innerInput match {
case head :: tail => head match {
case Some(value) => inner(tail, value::acc)
case _ => inner(tail, acc)
}
case _ => acc
}
inner(input, Nil)
}

Scala Tuple Option

If I have Scala tuple Option of the likes:
(Some(1), None)
(None, Some(1))
(None, None)
And I want always to extract always the "Some" value if it exists, and otherwise get the None. The only way with pattern matching?
There is this:
def oneOf[A](tup: (Option[A], Option[A])) = tup._1.orElse(tup._2)
That will return the first option that is defined, or None if neither is.
Edit:
Another way to phrase the same thing is
def oneOf[A](tup: (Option[A], Option[A])) =
tup match { case (first, second) => first.orElse(second) }
It's longer, but perhaps more readable.
This should work:
def f(t: (Option[Int], Option[Int])): Option[Int] = t match {
case (Some(n), _) => Some(n)
case (_, Some(n)) => Some(n)
case _ => None
}
I want always to extract always the Some value if it exists, and otherwise get the None
You can just use orElse
def orOption[T](p: (Option[T], Option[T])): Option[T] = {
val (o1, o2) = p
o1 orElse o2
}
However, this does decide what to do if there exists two Some values:
scala> orOption((Some(1), Some(2)))
res0: Option[Int] = Some(1)
You should probably use pattern matching and then decide what to do if there are two Some values, like throw an exception. Alternatively, consider using a better encoding for the result type than Option.

removing alternating elements on a list in scala

I am trying to write a recursive function in scala that takes in a list of Strings and returns a list with alternating elements from original list:
For example:
List a = {"a","b","c"}
List b = {"a","c"}
the head should always be included.
def removeAlt(list:List[String], str:String):List[String]=lst match{
case Nil=> List()
case => head::tail
if(head == true)
removeAlternating(list,head)
else
head::removeAlternating(list,head)
I get a stack overflow error.
I understand that the code is incorrect but I am trying to understand the logic on how to accomplish this with only recursion and no built in classes.
def remove[A](xs:List[A]):List[A] = xs match {
case Nil => Nil
case x::Nil => List(x)
case x::y::t => x :: remove(t)
}
if the list is empty, return a empty list.
If we're at the last element of the list, return that.
Otherwise, there must be two or more elements. Add to the first element the alternate elements of the rest of the list (and omit the second element)
Great exercise. This is what I came up with. It is not super optimized or anything:
def altList[T](rest: List[T], skip: Boolean): List[T] = {
rest match {
case Nil => Nil
case a :: tail if skip == false => a :: altList(tail, true)
case a :: tail if skip == true => altList(tail, false)
}
}
A bit shorter alternative:
def remove[A](xs:List[A]):List[A] = xs match {
case x::_::t => x :: remove(t)
case _ => xs
}
UPDATE
What is not so good with the above approach is eventual stack overflow for long lists, so I would suggest tail recursion:
import scala.annotation.tailrec
def remove[A](xs:List[A]):List[A] = {
#tailrec
def remove_r(xs:List[A], ys:List[A]):List[A] = xs match {
case x::_::t => remove_r(t, x::ys)
case _ => xs ++ ys
}
remove_r(xs, Nil).reverse
}

Whats wrong with this scala tuple?

Trying to create a method that determines if a set is a subset of another set, both given as parameters. When I tried to test it the console printed out
scala.MatchError : (List(1, 2, 3, 4, 5, 6, 7),List(1, 2, 3, 4)) (of class scala.Tuple2),
the two lists given are what I was using as parameters to test it. Also, scala was making me type out return in front of true and false, any ideas what led to this either?
def subset(a: List[Int], b: List[Int]): Boolean ={
(a,b) match {
case (_,Nil)=> return true
}
b match {
case h::t if (a.contains(h)) => subset(a,t)
case h::t => return false
}}
The other answers don't really answer exactly why your code is incorrect. It appears that you're handling the case when list b is empty and non-empty and that everything should be okay, but in fact you're actually not. Let's look at your code again, with some formatting fixes.
def subset(a: List[Int], b: List[Int]): Boolean = {
(a, b) match {
case (_, Nil) => return true
} // we can never make it past here, because either we return true,
// or a MatchError is raised.
b match {
case h :: t if (a.contains(h)) => subset(a,t)
case h :: t => return false
}
}
The real problem here is that you have two completely disconnected match statements. So when b is non-empty, the first match will fail, because it only handles the case when b is Nil.
As pointed out in the other solutions, the proper way to do this is to merge the two match statements together into one.
def subset(a: List[Int], b: List[Int]): Boolean = {
(a, b) match {
case (_, Nil) => true
case (xs, head :: tail) if(xs contains head) => subset(xs, tail)
case _ => false
}
}
Notice how the return statements are no longer needed. In scala you should avoid using return as much as possible, as it's likely that your way of thinking around return actually lead you into this trap. Methods that return early are likely to lead to bugs, and are difficult to read.
A cleaner way to implement this could use diff. b can be considered a subset of a if the set of elements of b minus the elements of a is empty.
def subset(a: List[Int], b: List[Int]): Boolean = (b.distinct diff a.distinct).nonEmpty
distinct is only required if it's possible for a and b to contain duplicates, because we're trying a List like a Set when it's actually not.
Better yet, if we convert the Lists to Sets, then we can use subsetOf.
def subset(a: List[Int], b: List[Int]): Boolean = b.toSet.subsetOf(a.toSet)
Scala match expression should match to at least one case expression. Otherwise the MatchError is raised.
You should have used the following cases:
(a, b) match {
case (_, Nil) => true
case (aa, h :: t) if aa contains h => subset(aa, t)
case _ => false
}
An alternative way could be to call methods in standard library.
For each element in 'b', check if 'a' contains that element.
Here is the simple code:
def subset(a: List[Int], b: List[Int]): Boolean = {
(b.forall(a.contains(_)))
}
MatchError - This class implements errors which are thrown whenever an object doesn't match any pattern of a pattern matching expression.
Obviously the second list having elements in it will cause this error, as no pattern will match. You should just add another branch to the first match like so:
def subset(a: List[Int], b: List[Int]): Boolean = {
(a, b) match {
case (_, List()) => return true
case _ => b match {
case h :: t if (a.contains(h)) => subset(a, t)
case h :: t => return false
}
}
}
MatchError occurs whenever an object doesn't match any pattern of a pattern matching expression.
An alternative way is by using dropWhile or takeWhile
def subsets(a:List[Int], b:List[Int]):Boolean = {
return b.dropWhile { ele => a.contains(ele)}.size==0
}
OR
def subsets(a:List[Int], b:List[Int]):Boolean = {
return b.takeWhile { ele => a.contains(ele)}.size==b.size
}

Scala Pattern Matching comparing a int to a list

I am trying to write a recursive program for comparing a int to each value in a list. Problem is I keep getting a unreachable error, and I really don't know why. My code is
def isIn(x : Int, l : List[Int]) : Boolean = l match {
case Nil => false
case x => true
case h :: t => isIn(x, t)
}
I really don't understand why this doesn't work. Or i guess, I am wondering how to compare x to the head using case.
The issue is that when you use a variable that starts with a lowercase character, the pattern matcher thinks that you are trying to assign to a new variable. Of course, a pattern that is simply an assignable variable will match anything, so any subsequent case will be unreachable.
To solve this, you need to use a "stable identifier". This can be done by putting the lowercased variable in backticks:
def isIn(x: Int, l: List[Int]): Boolean =
l match {
case Nil => false
case `x` :: t => true
case h :: t => isIn(x, t)
}
or renaming the variable so that it starts with an uppercase character:
def isIn(X: Int, l: List[Int]): Boolean =
l match {
case Nil => false
case X :: t => true
case h :: t => isIn(X, t)
}
Note that since each case must be a List, you need to have the :: t after x to show that x should be matching the head of the List.