Below is my code. Could someone explain to me what the problem is and how can I resolve it?
def max(list: List[Int]): Int =
if (list.isEmpty) throw java.util.NoSuchElementException()
else checkIfAnElementHigherThenOthers(list.head, list.tail)
#tailrec
def checkIfAnElementHigherThenOthers(accum: Int, list: List[Int]): Int =
if (accum < list.head) checkIfAnElementHigherThenOthers(list.head, list.tail)
else checkIfAnElementHigherThenOthers(accum, list.tail)
if (list.isEmpty) throw java.util.NoSuchElementException()
this statement returns Unit, but function is declared to return Int, so the compiler complains. Removing else following it, should fix it.
(By "it") I mean the compilation error ... your function logic is still wrong :) (hint: your checkIf... function never returns, there is no case when it would not end up calling itself (or erroring out)).
Related
This simple regex implementation (scastie here) does not compile, where I expected it to. The error is at line 14, where an intermediate recursive call is interpreted as to break the #tailrec requirement. While this intermediate recursive call is indeed not in tail-call position, the actual last call of the expression is, making the complete expression tail-call optimized.
This line of reasoning can be illustrated by aliasing the intermediate recursive call, turning it into an 'arbitrary' call. When the this call is aliased by aliasMatches, the code compiles and executes as expected.
Why doesn't the compiler accepts the non-aliased implementation? Is this a practical limitation, or is there something wrong with the reasoning above? Is there a way to coax the compiler in accepting the first version (other than a complete accumulator-rewrite) that I'm missing?
(using Scala 2.13.5)
import scala.annotation.tailrec
def matches(input: String, pattern: String): Boolean = {
#tailrec
def matchesRemainder(remainder: Seq[Char], remainingPattern: Seq[Char]): Boolean =
(remainder, remainingPattern) match {
case (Seq(), Seq()) => true
case (Seq(_#_*), Seq()) => false
case (Seq(), Seq(_, '*', _#_*)) => true
case (Seq(), Seq(_#_*)) => false
\\ vvvv error vvvv
case (Seq(_, rs#_*), Seq('.', '*', xs#_*)) => matchesRemainder(rs, remainingPattern) ||
matchesRemainder(remainder, xs)
case (Seq(r, rs#_*), Seq(p, '*', xs#_*)) => (r == p && aliasMatches(rs, remainingPattern)) ||
matchesRemainder(remainder, xs)
case (Seq(_, rs#_*), Seq('.', ps#_*)) => matchesRemainder(rs, ps)
case (Seq(r, rs#_*), Seq(p, ps#_*)) => r == p && matchesRemainder(rs, ps)
}
def aliasMatches(remainder: Seq[Char], p: Seq[Char]): Boolean =
matchesRemainder(remainder, p)
matchesRemainder(input, pattern)
}
Let's simplify it a little bit, to see the problem more clearly.
#tailrec
def foo(x: Int): Boolean = x == 0 || foo(x-1) || foo(x-2)
This does not compile, because it cannot eliminate recursion completely: foo(x-1) has to return control back to the caller, so in can evaluate the result and either return it, or call foo(x-2).
Tail recursion can only happen when the result of the recursive call is directly returned right away, without the control returning to the caller.
Now why does this compile?
def bar(x: Int) = foo(x)
#tailrec
def foo(x: Int): Boolean = x == 0 || bar(x-1) || foo(x-2)
Well, that's just cheating :) The compiler doesn't expect you to be that cunning, it has no way of knowing that bar is just going to call foo, so it has to trust you on that.
Basically #tailrec can only detect the immediate recursion if you try to mask it ... well, you will succeed :)
Remove || foo(x-2) from the above – it'll stop compiling, and tell you there is no recursion. Even though it is now a perfectly tail-recursive function, it will not be able to optimize it.
It's not a golden bullet. Here's another quirk:
#tailrec
def foo(x: => Future[Int]): Future[Int] = {
x.recoverWith { case _ => foo(x) }
foo(Future(1))
}
This is tail-recursive, but it will refuse to compile, because it does not realize that the first call to foo doesn't actually happen inside the outer foo.
I'm messing around with the assignments on Coursera's Functional Programming course and I've stumbled upon something weird. This problem requires you to find the max of a List of integers using only the methods isEmpty, head, and tail. My solution is a recursive function that catches an UnsupportedOperationException if there are no more elements. The solution doesn't seem to work however, and I think it is because the exception is never caught.
/**
* This method returns the largest element in a list of integers. If the
* list `xs` is empty it throws a `java.util.NoSuchElementException`.
*
* You can use the same methods of the class `List` as mentioned above.
*
* ''Hint:'' Again, think of a recursive solution instead of using looping
* constructs. You might need to define an auxiliary method.
*
* #param xs A list of natural numbers
* #return The largest element in `xs`
* #throws java.util.NoSuchElementException if `xs` is an empty list
*/
def max(xs: List[Int]): Int =
{
def maxOfTwo(value1: Int, value2: Int) = {
if(value1 > value2) value1
else value2
}
println(xs.size)
try { maxOfTwo(xs.head, max(xs.tail)) }
catch { case noTail: UnsupportedOperationException => xs.head }
}
When I use the following code, which is just replacing the UnsupportedOperationException with Exception everything works perfectly. Am I missing something here?
def max(xs: List[Int]): Int =
{
def maxOfTwo(value1: Int, value2: Int) = {
if(value1 > value2) value1
else value2
}
println(xs.size)
try { maxOfTwo(xs.head, max(xs.tail)) }
catch { case noTail: Exception => xs.head }
}
I think this would be better:
def max(xs: List[Int]): Option[Int] = {
#tailrec
def go(l: List[Int], x: Int): Int = {
l match {
case Nil => x
case h :: t => if (x > h) go(t, x) else go(t, h)
}
}
if (xs.isEmpty) None else Some(go(xs.tail, xs.head))
}
Result type is Option, because list can be empty.
UPDATE:
It fails when UnsupportedOperationException is used, because when you try to access xs.head of an empty list you should also catch NoSuchElementException. It works with Exception, because it's a base class of these two exceptions.
You can't catch java.util.NoSuchElementException with UnsupportedOperationException pattern.
And BTW your code is throwing exception twice. The second exception is thrown by catch block, by invoking xs.head.
How about just thinking functional?
def sum(xs: List[Int]): Int = {
if (xs.isEmpty) 0 else xs.head + sum (xs.tail)
}
In the below code - quite trivial max and sum of lists - I have a recursive function called at the end of a method. Will the scala compiler treat this as tail recursive and optimize the stack frame usage? How do I know/how can I verify this?
package example
import common._
object Lists {
def sum(xs: List[Int]): Int = {
def recSum(current: Int, remaining: List[Int]): Int = {
if (remaining.isEmpty) current else recSum(current + remaining.head, remaining.drop(1))
}
recSum(0, xs)
}
def max(xs: List[Int]): Int = {
def recMax(current: Int, remaining: List[Int], firstIteration: Boolean): Int = {
if(remaining.isEmpty){
current
}else{
val newMax = if (firstIteration || remaining.head>current) remaining.head else current
recMax(newMax, remaining.drop(1), false)
}
}
if (xs.isEmpty) throw new NoSuchElementException else recMax(0, xs, true)
}
}
Add #tailrec before function definition to make the compiler cause an error on non-tailrecursive methods :)
Also, you have to assume the function will be as efficient as an imperative loop (aka. for/while loop) when you have it optimized in this way by the compiler.
I'm trying to write a scala function which will recursively sum the values in a list. Here is what I have so far :
def sum(xs: List[Int]): Int = {
val num = List(xs.head)
if(!xs.isEmpty) {
sum(xs.tail)
}
0
}
I dont know how to sum the individual Int values as part of the function. I am considering defining a new function within the function sum and have using a local variable which sums values as List is beuing iterated upon. But this seems like an imperative approach. Is there an alternative method ?
Also you can avoid using recursion directly and use some basic abstractions instead:
val l = List(1, 3, 5, 11, -1, -3, -5)
l.foldLeft(0)(_ + _) // same as l.foldLeft(0)((a,b) => a + b)
foldLeft is as reduce() in python. Also there is foldRight which is also known as accumulate (e.g. in SICP).
With recursion I often find it worthwhile to think about how you'd describe the process in English, as that often translates to code without too much complication. So...
"How do I calculate the sum of a list of integers recursively?"
"Well, what's the sum of a list, 3 :: restOfList?
"What's restOfList?
"It could be anything, you don't know. But remember, we're being recursive - and don't you have a function to calculate the sum of a list?"
"Oh right! Well then the sum would be 3 + sum(restOfList).
"That's right. But now your only problem is that every sum is defined in terms of another call to sum(), so you'll never be able to get an actual value out. You'll need some sort of base case that everything will actually reach, and that you can provide a value for."
"Hmm, you're right." Thinks...
"Well, since your lists are getting shorter and shorter, what's the shortest possible list?"
"The empty list?"
"Right! And what's the sum of an empty list of ints?"
"Zero - I get it now. So putting it together, the sum of an empty list is zero, and the sum of any other list is its first element added to the sum of the rest of it.
And indeed, the code could read almost exactly like that last sentence:
def sumList(xs: List[Int]) = {
if (xs.isEmpty) 0
else xs.head + sumList(xs.tail)
}
(The pattern matching versions, such as that proposed by Kim Stebel, are essentially identical to this, they just express the conditions in a more "functional" way.)
Here's the the "standard" recursive approach:
def sum(xs: List[Int]): Int = {
xs match {
case x :: tail => x + sum(tail) // if there is an element, add it to the sum of the tail
case Nil => 0 // if there are no elements, then the sum is 0
}
}
And, here's a tail-recursive function. It will be more efficient than a non-tail-recursive function because the compiler turns it into a while loop that doesn't require pushing a new frame on the stack for every recursive call:
def sum(xs: List[Int]): Int = {
#tailrec
def inner(xs: List[Int], accum: Int): Int = {
xs match {
case x :: tail => inner(tail, accum + x)
case Nil => accum
}
}
inner(xs, 0)
}
You cannot make it more easy :
val list = List(3, 4, 12);
println(list.sum); // result will be 19
Hope it helps :)
Your code is good but you don't need the temporary value num. In Scala [If] is an expression and returns a value, this will be returned as the value of the sum function. So your code will be refactored to:
def sum(xs: List[Int]): Int = {
if(xs.isEmpty) 0
else xs.head + sum(xs.tail)
}
If list is empty return 0 else you add the to the head number the rest of the list
The canonical implementation with pattern matching:
def sum(xs:List[Int]) = xs match {
case Nil => 0
case x::xs => x + sum(xs)
}
This isn't tail recursive, but it's easy to understand.
Building heavily on #Kim's answer:
def sum(xs: List[Int]): Int = {
if (xs.isEmpty) throw new IllegalArgumentException("Empty list provided for sum operation")
def inner(xs: List[Int]): Int = {
xs match {
case Nil => 0
case x :: tail => xs.head + inner(xs.tail)
}
}
return inner(xs)
}
The inner function is recursive and when an empty list is provided raise appropriate exception.
If you are required to write a recursive function using isEmpty, head and tail, and also throw exception in case empty list argument:
def sum(xs: List[Int]): Int =
if (xs.isEmpty) throw new IllegalArgumentException("sum of empty list")
else if (xs.tail.isEmpty) xs.head
else xs.head + sum(xs.tail)
def sum(xs: List[Int]): Int = {
def loop(accum: Int, xs: List[Int]): Int = {
if (xs.isEmpty) accum
else loop(accum + xs.head, xs.tail)
}
loop(0,xs)
}
def sum(xs: List[Int]): Int = xs.sum
scala> sum(List(1,3,7,5))
res1: Int = 16
scala> sum(List())
res2: Int = 0
To add another possible answer to this, here is a solution I came up with that is a slight variation of #jgaw's answer and uses the #tailrec annotation:
def sum(xs: List[Int]): Int = {
if (xs.isEmpty) throw new Exception // May want to tailor this to either some sort of case class or do something else
#tailrec
def go(l: List[Int], acc: Int): Int = {
if (l.tail == Nil) l.head + acc // If the current 'list' (current element in xs) does not have a tail (no more elements after), then we reached the end of the list.
else go(l.tail, l.head + acc) // Iterate to the next, add on the current accumulation
}
go(xs, 0)
}
Quick note regarding the checks for an empty list being passed in; when programming functionally, it is preferred to not throw any exceptions and instead return something else (another value, function, case class, etc.) to handle errors elegantly and to keep flowing through the path of execution rather than stopping it via an Exception. I threw one in the example above since we're just looking at recursively summing items in a list.
Tried the following method without using substitution approach
def sum(xs: List[Int]) = {
val listSize = xs.size
def loop(a:Int,b:Int):Int={
if(a==0||xs.isEmpty)
b
else
loop(a-1,xs(a-1)+b)
}
loop(listSize,0)
}
Suppose I have following code
def foo(x:Int):Unit = {
if (x == 1) println ("done")
else foo(scala.util.Random.nextInt(10))
}
Is it guaranteed that the compiler does tail recursion optimization?
Yes. To know for sure add the #tailrec annotation to your method. This will cause the compiler to throw an error if it does not compile using tail recursion.
#tailrec
def foo(x:Int):Unit = {
if (x == 1) println ("done")
else foo(scala.util.Random.nextInt(10))
}
No, the Unit return type is irrelevant.
scala> #tailrec def f(i: Int) { if (i >= 0) { println(i); f(i - 1) } }
f: (i: Int)Unit
But:
scala> #tailrec def f(i: Int) { if (i >= 0) { f(i - 1); println(".") } }
<console>:11: error: could not optimize #tailrec annotated method f:
it contains a recursive call not in tail position
You need to have the recursive call as the last call, return type does not matter.
Your code in the question is fine but the title of the question would be misleading.