Scala recursive function returning Either - scala

I'm writing a recursive function which returns False or a List of values.
def parse(chars: List[Char]): Either[List[Char], Boolean] = {
if (chars.length == 1)
chars
else {
val head = chars.head
val tail = parse(chars.tail)
tail match {
case Left(l) => {
if (are_equal(head, tail.head))
head :: tail
else if (are_cancelled(head, tail.head))
tail.tail
else
false
}
case Right(b) => false
}
}
}
I'm getting error: value head is not a member of Either[List[Char],Boolean], but head method should only be used after matching the list.

The pattern match tail match { ... } doesn't magically change the type of the value you're matching on. tail is still an Either and Either doesn't have a member head. But l is a List, so replace tail.head with l.head and so on.
You can try inserting explicit type annotation to make things clearer.
Your return types are also wrong in a few places. Here's a version that's closer to compiling:
def parse(chars: List[Char]): Either[List[Char], Boolean] = {
if (chars.length == 1) {
Left(chars)
} else {
val head = chars.head
val tail = parse(chars.tail)
tail match {
case Left(l) =>
if (are_equal(head, l.head))
Left(head :: l)
else if (are_cancelled(head, l.head))
Left(l.tail)
else
Right(false)
case Right(b) => Right(false)
}
}
}

Related

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
}

could not optimize #tailrec annotated method loop: it contains a recursive call not in tail position

I have the following recursive function which I want to use tail recursion on it. But compiler complains about my implementation with this error:Error:(79, 7) could not optimize #tailrec annotated method loop: it contains a recursive call not in tail position
n match {
^
is it because of for loop that it assumes it's not in tail position?
def dsl[N,E](qNodes:QNodeLike[N,E]*) = {
val markers = scala.collection.mutable.Map.empty[String, N]
#tailrec
def loop(n:QNodeLike[N,E]):Unit = {
n match {
case QNode(head, kids:Seq[HalfEdgeLike[E,N]]) => {
for(kid <- kids){
kid match {
case EmptyHalfEdge() =>
case HalfEdge(e, n) => loop(n)
}
}
}
case QNodeMarker(head, marker, kids:Seq[HalfEdgeLike[E,N]]) => {
markers.update(marker,head)
for(kid <- kids){
kid match {
case EmptyHalfEdge() =>
case HalfEdge(e, n) => loop(n)
}
}
}
}
}
loop(qNodes.head)
}
Yes, that's right. To make it tail recursive, you should use an explicit accumulator which is passed into the recursion.
However, unless you have very deep and narrow trees, you are unlikely to need tail recursive optimization, as the run time will grow very large well before you end up with a stack overflow.
Here's a rough idea of how to make it tail optimized:
#tailrec
def loop(n:List[QNodeLike[N,E]]):Unit = {
n match {
case QNode(head, kids:Seq[HalfEdgeLike[E,N]]) :: rem => {
kids match {
case Nil =>
case EmptyHalfEdge() :: rem2 => loop(rem2 ::: rem)
case HalfEdge(e, n) :: rem2 => loop(n :: rem2 ::: rem)
}
}
case QNodeMarker(head, marker, kids:Seq[HalfEdgeLike[E,N]]) :: rem => {
markers.update(marker,head)
kids match {
case Nil =>
case EmptyHalfEdge() :: rem2 => loop(rem2 ::: rem)
case HalfEdge(e, n) :: rem2 => loop(n :: rem2 ::: rem)
}
}
case Nil =>
}
}
Yes it is because of the loop. The result of a tailrec funtion has to be the result of the recursive call. In your case the result is the result of the for statement.

Required return keyword

So I am relatively new to Scala and working through Functional Programming in Scala and just ran across something new in one of the practice problems. In hasSequences, I am required to place the return keyword in front of my return value or else nothing will return and the next line will execute. Why is this required?
def hasSubsequence[A](list: List[A], subList: List[A]) : Boolean = {
def matcher(l: List[A], sl: List[A]): List[A] = {
if (sl.isEmpty) return Nil
l match {
case Nil => Nil
case head :: tail if (head == sl.head) => head :: matcher(tail, sl.tail)
case head :: tail => matcher(tail, sl)
case _ => Nil
}
}
if (matcher(list, subList) == subList) true else false
}
It's required because Scala treats the return value as either the last value in the function, or a value following the return keyword. Since your example isn't the last thing in the function, how would Scala know you wanted to return it? Imagine a situation where you use a function with side effects which also has a return value. If you call the function without assigning the result to anything, there would be no way to determine if you wanted to return that value or not without these restrictions.
You could modify your function like this:
def hasSubsequence[A](list: List[A], subList: List[A]) : Boolean = {
def matcher(l: List[A], sl: List[A]): List[A] = {
if (sl.isEmpty) Nil
else l match {
case Nil => Nil
case head :: tail if (head == sl.head) => head :: matcher(tail, sl.tail)
case head :: tail => matcher(tail, sl)
case _ => Nil
}
}
if (matcher(list, subList) == subList) true else false
}
to avoid the return. Since this makes the match part of the same if statement as the return, it all becomes part of the latest statement, and you no longer need to explicitly return.

error: #tailrec annotated method contains no recursive calls

When running this piece of code:
object P01 {
#annotation.tailrec
final def lastRecursive[A] (ls:List[A]):A = {
def lr[A] (l:List[A]):A = l match {
case h :: Nil => h
case _ :: tail => lr(tail)
case _ => throw new NoSuchElementException
}
lr(ls)
}
}
P01.lastRecursive(List(1,2,3))
,in scala 2.10.2 REPL, I get the following error:
scala> :9: error: #tailrec annotated method contains no recursive calls
final def lastRecursive[A] (ls:List[A]):A = {
^
Please help, I don't understand what am I doing wrong.
lastRecursive isn't tail recursive but lr is. This worked for me:
object P01 {
final def lastRecursive[A] (ls:List[A]):A = {
#annotation.tailrec
def lr[A] (l:List[A]):A = l match {
case h :: Nil => h
case _ :: tail => lr(tail)
case _ => throw new NoSuchElementException
}
lr(ls)
}
}

Is there a way to break out of #tailrec in Scala?

I have a method that is recursive. Is there a way in scala to break out based on the size of the buffer (as shown below)? A case for breaking out when elementList.size > 5 for example?
val elementList = ListBuffer.empty[Book]
#tailrec
def getBooks(elements: List[Element]) {
elements match {
case Nil => info("Reached end of elements list.")
case element :: rest if element.getElementType == ElementType.BOOK => {
elementList.append(element.getBook)
getLooks(rest)
}
case _ => getBooks(elements.tail)
}
}
I guess the most simple way would be to just wrap an if statement around your match statement like this:
val elementList = ListBuffer.empty[Book]
#tailrec
def getBooks(elements: List[Element]) {
if (elementList.size <= 5){
elements match {
case Nil => info("Reached end of elements list.")
case element :: rest if element.getElementType == ElementType.BOOK => {
elementList.append(element.getBook)
getLooks(rest)
}
case _ => getBooks(elements.tail)
}
}
}
Genereally speaking you could try to pass down the number of remaining elements in the recursion.
For example:
def get(list: List[Int], max: Int): List[Int] = {
#tailrec
def get(list: List[Int], acc: List[Int], remaining: Int): List[Int] = {
list match {
case h :: tail if remaining > 0 =>
get(tail, h :: acc, remaining - 1)
case _ =>
acc
}
}
// Requires reverse() !
get(list, Nil, max).reverse
As for the accumulator: you could use a buffer instead, to prevent the reverse() at the end.