Required return keyword - scala

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.

Related

Scala recursive function returning Either

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

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
}

Sorting function in Scala runs for a long time

I am trying to write a recursive function in SCALA that take sin a list and sorts it.
However, the code seems to run for a long time. It doesn't even give me an error message.
def sort(list:List[Int]):List[Int] = list match{
case Nil => Nil
case h::t => insert (h, sort(t))
def insert(num:Int, list:List[Int]): List[Int]=list match{
case Nil => List()
case head::tail=>
if(head>=num)
num::list
else
head::insert(num,tail)
}
sort(list)
}
You had 2 problems:
1) you are calling sort recursively from sort function directly - remove sort(list) because insert already calls it. This will make it terminate.
2) you return an empty list in one of the cases instead of constructing a list with 1 elem - base case is wrong.
This version works:
def sort(list: List[Int]): List[Int] = {
def insert(num: Int, list: List[Int]): List[Int] = list match {
case Nil => num :: Nil
case head::tail =>
if(head >= num)
num::list
else
head::insert(num, tail)
}
list match {
case Nil => Nil
case h::t => insert(h, sort(t))
}
}

How can i transform this scala function in order to be optimized

Code to determine the lat element of a list, using pattern matching:
#tailrec
def last_rec[A](list : List[A]) : A = {
list match {
case (x :: Nil) => x
case (_ :: xs) => last_rec(xs)
case Nil => throw new NoSuchElementException
}
}
I want to compile the code, I am getting "yelled" by the compiler:
PS D:\workspace\scala\P99> scalac .\P01.scala
.\P01.scala:18: error: could not optimize #tailrec annotated method last2: it contains a recursive call not in tail position
case Nil => throw new NoSuchElementException
^
one error found
If I remove the #tailrec annotation - the code compiles . How can I modify the code in order to do the tail rec optimization ?
You got a typo their. Your method is called last_rec and you are calling last which is clearly undefined. So just rename it to last. And by the way you should return Option[A] instead of A. That way you can return None when nothing is found instead of throwing the ugly NoSuchElementException.
After removing the typo and adding agilesteel's suggestion:
#tailrec
def last_rec[A](list : List[A]) : Option[A] = {
list match {
case (x :: Nil) => Some(x)
case Nil => None
case (_ :: xs) => last_rec(xs)
}
}
In this case I would do what agilesteel suggested.
However, if you really wanted to throw an exception (in another different use case), you could do it in a statically typed way:
#tailrec
def last_rec[A](list : List[A]) : Either[NoSuchElementException,A] = {
list match {
case (x :: Nil) => Right(x)
case (_ :: xs) => last_rec(xs)
case Nil => Left(new NoSuchElementException)
}
}
where later you could:
last_rec(Nil) match {
case Right(s) => println("Got a value")
case Left(e) => println("Got an exception")
}

scala pattern matching

It seems the type of Nil is not polymorphic. How do I correct this function:
scala> def last[A](a:List[A]) : A =
| a match {
| case _ :: tail => last(tail)
| case Nil => Nil[A]
| }
<console>:8: error: object Nil does not take type parameters.
case Nil => Nil[A]
UPDATE:
scala> def last[A](a : List[A] ) : Option[A] =
| a match {
| case head :: Nil => Some(head)
| case _ :: tail => last(tail)
| case Nil => None
| }
Nil is an object, not a type. So Nil[A] doesn't make any sense.
An empty list does not have a last element. As such invoking last on Nil should throw an error.
def last[A](l: List[A]): A = l match {
case x :: Nil => x
case _ :: tail => last(tail)
case Nil => sys.error("An empty list")
}
Alternatively you could have last return an Option[A] as shown below:
def last[A](l: List[A]): Option[A] = l match {
case x :: Nil => Some(x)
case _ :: tail => last(tail)
case Nil => None
}
The error is that you've declared the method to return A:
def last[A](a:List[A]) : A
^^^
and the empty list, Nil is not an A.
(And (as a side-note), as the error message says, Nil does not take type parameters.)
A better return type for a last function is probably Option[A]. Your method definition, but with Option[A] would look like:
scala> def last[A](a: List[A]): Option[A] =
| a match {
| case x :: Nil => Some(x)
| case _ :: tail => last(tail)
| case Nil => None
| }
last: [A](a: List[A])Option[A]
When you need to tell the compiler what type Nil should be, you can use type ascription, like this:
Nil: List[A]
But, as aioobe pointed out, this won't solve your problem. Nil is an empty list, not the last element of a list.
The object Nil extends List[Nothing]. Nothing is a sub-type of everything (similar as Any is the super-type of everything), and List is covariant (denoted as List[+A]), which means that Nil will fit as endpoint for every list.
However, as a result of this construction, there are situations where the compiler can't infer the correct type of an empty list, and you need to give a hint (as shown by Ben James). BTW, the same applies to the object None as sub-class of Option.