Tail recursion and call by name / value - scala

Learning Scala and functional programming in general. In the following tail-recursive factorial implementation:
def factorialTailRec(n: Int) : Int = {
#tailrec
def factorialRec(n: Int, f: => Int): Int = {
if (n == 0) f else factorialRec(n - 1, n * f)
}
factorialRec(n, 1)
}
I wonder whether there is any benefit to having the second parameter called by value vs called by name (as I have done). In the first case, every stack frame is burdened with a product. In the second case, if my understanding is correct, the entire chain of products will be carried over to the case if ( n== 0) at the nth stack frame, so we will still have to perform the same number of multiplications. Unfortunately, this is not a product of form a^n, which can be calculated in log_2n steps through repeated squaring, but a product of terms that differ by 1 every time. So I can't see any possible way of optimizing the final product: it will still require the multiplication of O(n) terms.
Is this correct? Is call by value equivalent to call by name here, in terms of complexity?

Let me just expand a little bit what you've already been told in comments.
That's how by-name parameters are desugared by the compiler:
#tailrec
def factorialTailRec(n: Int, f: => Int): Int = {
if (n == 0) {
val fEvaluated = f
fEvaluated
} else {
val fEvaluated = f // <-- here we are going deeper into stack.
factorialTailRec(n - 1, n * fEvaluated)
}
}

Through experimentation I found out that with the call by name formalism, the method becomes... non-tail recursive! I made this example code to compare factorial tail-recursively, and factorial non-tail-recursively:
package example
import scala.annotation.tailrec
object Factorial extends App {
val ITERS = 100000
def factorialTailRec(n: Int) : Int = {
#tailrec
def factorialTailRec(n: Int, f: => Int): Int = {
if (n == 0) f else factorialTailRec(n - 1, n * f)
}
factorialTailRec(n, 1)
}
for(i <-1 to ITERS) println("factorialTailRec(" + i + ") = " + factorialTailRec(i))
def factorial(n:Int) : Int = {
if(n == 0) 1 else n * factorial(n-1)
}
for(i <-1 to ITERS) println("factorial(" + i + ") = " + factorial(i))
}
Observe that the inner tailRec function calls the second argument by name. for which the #tailRec annotation still does NOT throw a compile-time error!
I've been playing around with different values for the ITERS variable, and for a value of 100,000, I receive a... StackOverflowError!
(The result of zero is there because of overflow of Int.)
So I went ahead and changed the signature of factorialTailRec/2, to:
def factorialTailRec(n: Int, f: Int): Int
i.e call by value for the argument f. This time, the portion of main that runs factorialTailRec finishes absolutely fine, whereas, of course, factorial/1 crashes at the exact same integer.
Very, very interesting. It seems as if call by name in this situation maintains the stack frames because of the need of computation of the products themselves all the way back to the call chain.

Related

How do you print an integer value within an object in scala?

object perMissing {
def solution(A: Array[Int]): Int = {
def findMissing(i: Int, L: List[Int]): Int = {
if (L.isEmpty || L.head != i+1) {
i+1
println(i+1)}
else findMissing(i+1, L.tail)
}
if (A.length == 0) 1
else findMissing(0, A.toList.sorted)
}
solution(Array(2,3,1,5))
}
I'm new to the world of Scala. I come from Python and C world.
How do we print an integer value, eg. for debugging? For instance, if I want to see the value of i in every iteration.
I compile my code using scalac and run it using scala.
According to the signature of your findMissing function, it should return an Int. However, if you look at the implementation of that function, only one of the code paths (namely the else part) returns an Int - the if part on the other hand does not return anything (besides Unit), since the call to println is the last line of that particular code block. To fix this issue, just return the increased value by putting it at the end of the block:
def findMissing(i: Int, l: List[Int]): Int = {
val inc = i + 1
if (l.isEmpty || l.head != inc) {
println(inc)
inc
}
else findMissing(inc, l.tail)
}
Since findMissing is tail recursive, you could additionally annotate it with #tailrec to ensure it will be compiled with tail call optimization.

Scala function with a recursive function parameter

I am curious if can implement a Scala function similar to this Javascript function. Obviously, I can do it easily with an inner function.
Knowing that Scala has to declare the parameter type and arity upfront, I just wonder if there is anything I could use to implement this JS function. Thanks.
function factorial(x) {
if (x < 0) throw Error("Cannot calculate factorial of a negative number");
return (function(f) {
return f(f, x, 1);
})(function(f, i, fact) {
return i === 0 ? fact : f(f, i-1, i*fact);
});
}
If I have understood your question correctly, indeed you can do this and the best known approach is to use what's called a Y-combinator. In short a Y-combinator takes a function as a parameter and keeps applying it. The Y-combinator has no knowledge of the parameter types involved
Copying the example Y-combinator right from rosetta code:
def Y[A,B](f: (A=>B)=>(A=>B)) = {
case class W(wf: W=>A=>B) {
def apply(w: W) = wf(w)
}
val g: W=>A=>B = w => f(w(w))(_)
g(W(g))
}
defines your combinator. You can then pass it your recursive function
val fac = Y[Int, Int](f => i => if (i <= 0) 1 else f(i - 1) * i)
fac: Int => Int = <function1>
And then give that something to evaluate
scala> fac(6)
res0: Int = 720

How do you call a function which takes a tuple of two as an argument and returns a tuple of two as a result in Scala?

I am very new to Scala. I have been assigned the task of coding the Fast Fibonacci algorithm. I am finding it difficult when it comes to actually calling the function. The function takes a tuple of two and returns a tuple of two as a result. I don't know if my logic for fibStep is correct but I will get to that as soon as I can actually test the function. The following is what I have so far:
def fastFib(x: Long ): Long = {
def fibStep(x:(Long, Long)): (Long, Long) = {
//setting temporary variables a and b
def a = x._1
def b = x._2
//applying the fast Fibonacci algorithm
def c = a * (b * 2 - a)
def d = a * a + b * b
if (c+d % 2 == 0) return (c,d)
else return (d, c+d)
}
def tuple = (x-1,x-2)
return fibStep(tuple)
}
I need to pass the tuple (x-1,x-2) to fibStep. How do I do it? Thanks
The problem is in return statement. You trying to return tuple, instead of Long.
Fix:
def fastFib(x: Long ): Long = {
...
return fibStep(tuple)._1 // or ._2
}
Note: I'm not sure if your algorithm is correct
You've got a number of problems here.
def is used to define functions
val should be used to define variables
return should not be used. You 'return' a result simply by it being the last value in an expression.
A tuple is defined simply using parenthesis:
val myTuple = (1,2)
With this information you should be able to make a better attempt at it.

Scala, Exercise with recursive function

Trying to solve the exercises in the book "Scala for the Impatient", I have a little problem. (Below are my solutions)
1: Write a for loop for computing the product of the Unicode codes of all letters in a string. For example, the product of the characters in "Hello" is 825152896
var p = 1; val S = "Hello"
for (i <- S) p*= i
println(p)
2: Solve the preceding exercise without writing a loop. (Hint: look at the String0ps Scaladoc.)
val St="Hello".map(_.toInt).product ; println(St)
3: Write a function product(s : String) that computes the product, as described in the preceding exercises.
def product(s: String)={
val S=s; println(S.map(_.toInt).product)
}
product("Hello")
Make the function of the preceding exercise a recursive function.
??? I do not know how to do it
I hope that someone can help me.
Best regards,
Francesco
Using well-known recursive functions and modifying them to comply with a different problem may prove quite a helpful approach.
Consider as a start-up pattern the factorial recursive function,
def factorial(n: Int): Int =
if (n <= 1) 1 else n * factorial (n-1)
Consider now the factorial recursive function where the input is assumed to be a list of integers from 1 to n, and so note the way the input list is reduced to the base case,
def factorial(xs: List[Int]): Int =
if (xs.isEmpty) 1 else xs.head * factorial (xs.tail)
This transformation is now closer to a solution for the original problem on string input.
Ok...finally my code works:
def prodRec(s: String): Int = {
if (s.toList.isEmpty) 1
else {
s.toList.head * prodRec(s.tail)
}
}
println(prodRec("Hello"))
I hope that this code snippet might help someone else...
best regards
francesco
Here is another way of writing the recursive solution to the product:
def getProduct(s: String):Int = {
def accumulate(acc:Int,ch:Array[Char]):Int = {
ch.headOption match {
case None => acc
case Some(x) => accumulate(acc*x.toInt,ch.tail)
}
}
accumulate(1,s.toArray)
}
Maybe I solved with:
def prodRec(s: String): Int = {
var s2 =s.toList
if (s2.isEmpty) 1
else {
s2.head * prodRec (s.tail)
}
}
My variant of tail recursive function. No vars used, which is a plus.
def product(s: String): Unit = {
#tailrec
def help(z: Long, array: Array[Char]): Long = {
if (array.isEmpty) z else help(z * array.head.toInt, array.tail)
}
print(help(1L, s.toCharArray))
}
def product (s:String): Long ={
if (s.length==1) s(0) else s.head * s.product (s.tail)
}

Scala tail recursion error

Below is a simple 'repeat' method I am trying to write using tail recursion. The sole purpose of this function is to just repeat the giving string back to back 'n' amount of times.
I.e. repeat("Hello",3) = "HelloHelloHello"
But for whatever reason I am getting a 'java.lang.UnsupportedOperationException' and I am not sure why.
P.S. This is a homework assignment so if I could just be pointed in the right direction instead of a straight answer that would be cool!
def repeat(s: String, n: Int): String = {
def tailRepeat(str: String, x: Int): String = x match {
case `n` => str
case _ => val repeatString = s + str
tailRepeat(repeatString, (x + 1))
}
tailRepeat(s, 0)
}
I think you are making this a little too complex. For one thing you don't really need pattern matching at all, you have a counting variable that tells you how many times to repeat your string, using that would simplify your code greatly. Also it is usually more straightforward to count down and not up:
def repeat(s: String, n: Int): String = {
def tailRepeat(str: String, x: Int): String = {
if(x == 0) str
else tailRepeat(str + s, x - 1)
}
tailRepeat(s, n - 1)
}
println( repeat("hello", 3) );
// hellohellohello