Method evaluation not behaving as expected - scala

Below code calculates the total a fibonacci sequence to a particular number.
But a StackOverFlow exception is being thrown. Why is this exception being thrown as I am checking
for 0 within the function ?
object fibonacci extends Application {
def fibonacci(i : Int) : Int = {
println(i)
if(i == 0) 0
if(i == 1) 1
fibonacci(i - 1) + fibonacci(i - 2)
}
fibonacci(3)
}
Error :
scala> fibonacci(3)
3
2
1
0
-1
-2
-3
-4
-5
-6
-7
-8
-9
.......
scala> fibonacci(3)
java.lang.StackOverflowError
at .fibonacci(<console>:10)
at .fibonacci(<console>:10)
at .fibonacci(<console>:10)
at .fibonacci(<console>:10)

def fibonacci(i : Int) : Int = {
println(i)
if (i == 0) 0
else if (i == 1) 1
else fibonacci(i - 1) + fibonacci(i - 2)
}
Without those else you're not stopping when you reach 0 or 1.

Scala will automatically evaluate the return value of a function to be the value of the last statement calculated (this is the reason you don't need the return keyword).
Without elses, your two if statements are stand-alone statements, but not the last statement in the function. They resolve to a value, but this value is not assigned to anything and so is thrown away and the function continues processing statements.
Putting elses in (as per #Marth's solution) ensures that you end the function with one single statement consisting of a single if-else chain. This whole statement (and hence, the function) evaluates to the result of whichever branch of the chain is selected and executed.
You can also acheive the effect you want using a match (which is also treated as one single statement):
def fibonacci(i : Int) : Int = {
println(i)
i match {
case 0 => 0
case 1 => 1
case _ => fibonacci(i - 1) + fibonacci(i - 2)
}
}

Related

What's wrong with my scala code in Functional Programming Principles in Scala of the first exercise

I'm a scala beginner. I'm learning Functional Programming in Scala. But I face this problem when I do the first exercise.here is the first exercise:
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
The numbers at the edge of the triangle are all 1, and each number
inside the triangle is the sum of the two numbers above it. Write a
function that computes the elements of Pascal’s triangle by means of a
recursive process.
Do this exercise by implementing the pascal function in Main.scala,
which takes a column c and a row r, counting from 0 and returns the
number at that spot in the triangle. For example, pascal(0,2)=1,
pascal(1,2)=2 and pascal(1,3)=3.
here is my first code:
package recfun
object Main {
def main(args: Array[String]) {
println("Pascal's Triangle")
for (row <- 0 to 10) {
for (col <- 0 to row)
print(pascal(col, row) + " ")
println()
}
}
var i = 0
/**
* Exercise 1
*/
def pascal(c: Int, r: Int): Int = {
if(c==r||c==0)
1
else
i = pascal(c - 1, r - 1) + pascal(c, r - 1)
i
}
/**
* Exercise 2
*/
def balance(chars: List[Char]): Boolean = ???
/**
* Exercise 3
*/
def countChange(money: Int, coins: List[Int]): Int = ???
}
but I get this result
0
0 0
0 0 0
0 0 0 0
0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
then I try to change my code,and I get correct result.
package recfun
object Main {
def main(args: Array[String]) {
println("Pascal's Triangle")
for (row <- 0 to 10) {
for (col <- 0 to row)
print(pascal(col, row) + " ")
println()
}
}
/**
* Exercise 1
*/
def pascal(c: Int, r: Int): Int = {
if(c==r||c==0)
1
else
pascal(c - 1, r - 1) + pascal(c, r - 1)
}
/**
* Exercise 2
*/
def balance(chars: List[Char]): Boolean = ???
/**
* Exercise 3
*/
def countChange(money: Int, coins: List[Int]): Int = ???
}
I want to know why my first code is worng?
There is problem in your first pascal function
i=0
def pascal(c: Int, r: Int): Int = {
if(c==r||c==0)
1
else
i = pascal(c - 1, r - 1) + pascal(c, r - 1)
i
}
In if-else block always var 'i' is returned which has value as 0. In else condition it is assigned but as recurring pascal will return initial 'i' value (0), it will be always 0.
It is not bad practise to use global variable in function only for returning any value so second approach is more correct still if you want to return value with global variable at least assign value in if and else block as below
i=0
def pascal(c: Int, r: Int): Int = {
if(c==r||c==0)
i=1 // this will be assigned for the first time and when r==c
else
i = pascal(c - 1, r - 1) + pascal(c, r - 1) // this will be assigned for subsequent calculations
i // it will return value which is calculated in if else block
}
**It is recommended to use proper curly braces {} to avoid such confusion.**
def pascal(c: Int, r: Int): Int = {
if(c==r||c==0){
i=1
} else{
i = pascal(c - 1, r - 1) + pascal(c, r - 1)
}
i
}
In the second code, you just have if-else block and no statement after this block and scala is smart and return from if and else block only.
Hope it answer your question.
In the second code the value of the if-statement is the result of the function. In the first function, i is the result of the function and the value of the if-statement is not used. So all that matters is what the if-statement does to i. The then-part of the if-statement doesn't do anything to i, so if the then-part is taken, the result will be the previous value of i, which will be 0.

Call `ConcurrentLinkedQueue.poll` on empty queue seems return 0 instead of null

Scala version 2.12.1-20161205-201300-2787b47
val max = 20
val queue = new java.util.concurrent.ConcurrentLinkedQueue[Int]()
(1 to 10).foreach(queue.offer)
def show(c: Int): Unit = {
val e = queue.poll()
if(c < max && e != null) {
println(e)
show(c + 1)
}
}
show(0)
Repl output
1
2
3
4
5
6
7
8
9
10
0
0
0
0
0
0
0
0
0
0
What happened ?
In Scala, Int extends AnyVal. Types that extend AnyVal cannot bind to a null value.
This code complies because there is boxing and unboxing happening behind the covers between Int and the Integer reference type. For example, to set the ConcurrentLinkedQueue with an Integer instead of an Int:
def apply$mcZI$sp(x$1: Int): Boolean = queue.offer(scala.Int.box(x$1));
And same goes when you pull out a value via offer, the compiler does:
val e: Int = unbox(queue.poll());
Where unbox goes to BoxesRunTime.unboxtoInt:
public static int unboxToInt(Object i) {
return i == null ? 0 : ((java.lang.Integer)i).intValue();
}
And that's why you see 0 instead of null. Be careful when doing such interop between Java classes in Scala.

Block statements in anonymous Scala function

I've created this simple anonymous function
var b = (x : Int) => if(x % 2 == 0) x + 1 else x
and it works great. After that I tried to add another statement after the if and before the x+1 statement.
var b = (x : Int) => if(x % 2 == 0) println(x) x + 1 else x
and a that point I received the following compiler error
Cannot resolve symbol x
Please can anyone let me know why this happen?
The reason this happens is that although Scala does not require the use of semi-colons most of the time (unlike Java), since the compiler is more equipped to infer where statements/expressions end, if you have 2 statements/expressions on 1 line then you need to separate them for the compiler.
Your first anonymous function works since if(x % 2 == 0) x + 1 else x is 1 expression.
The compiler is complaining with the second one though since if(x % 2 == 0) println(x) is considered 1 statement. Hence, the next statement starts and there is now no context for x.
Other posters have given you a solution to break the right-side of the function down into separate statements so I won't duplicate - just adding an explanation of why the compilation error occurs since you said you are learning the language. Google about the use of semi-colons in Scala to find out more.
Use this. You need the braces to indicate these are multiple lines:
var b = (x : Int) => if(x % 2 == 0) {
println(x)
x + 1
} else x
Or you can do this.. you need to put that semi colon to indicate to compiler they are separate statements:
var b = (x : Int) => if(x % 2 == 0) { println(x); x + 1 } else x

Tail Recursion in Scala with Base case as zero

Suppose I have this code in scala :
def factorial(accumulator: Int, x: Int) : Int = {
if(x == 1)
return accumulator
factorial(x * accumulator, x - 1)
}
println(factorial(1,0))
And the Output :
0
Now I have two questions :
1) Isn't the definition of this function fundamentally wrong? ( will not give the right answer for zero) I could always wrap this function inside another function and treat zero as special case returning 1 but that does not feel right and in tune with the formal definition.
2) Also why I am returned 0 as the answer in the first place? Why doesn't the code get stuck in an infinite loop?
def factorial(x: Int): Int = {
#annotation.tailrec
def factorial(accumulator: Int, x: Int): Int = {
if (x <= 0)
accumulator
else
factorial(x * accumulator, x - 1)
}
assert(x >= 0,"""argument should be "non-negative integer" """)
factorial(1, x)
}
You should not give user possibility to call factorial in wrong way. So your function should be internal
factorial(0) = 1
Yes, you should hide the accumulator and make it an argument of an internal, tailrec function. The special case for zero should also be handled explicitly, there is nothing 'against formal factorial definition' with it.
It works because integer exceeds the maximum negative value.

Do if else statements in Scala always require an else?

I have the following function which works fine:
def power(x: Double, n: Int) : Double = {
if (n > 0 && n % 2 == 0) power(x, n/2) * power(x, n/2)
else if (n > 0 && n % 2 == 1) x * power(x, n-1)
else if (n < 0) 1 / power(x, -n)
else 1
}
If I change it to be:
def power(x: Double, n: Int) : Double = {
if (n > 0 && n % 2 == 0) power(x, n/2) * power(x, n/2)
else if (n > 0 && n % 2 == 1) x * power(x, n-1)
else if (n < 0) 1 / power(x, -n)
else if (n==0 ) 1
}
I.e. change the final else statement to be an else if, then I get the following error trying to call the function:
> <console>:8: error: not found: value power
power(2, 1)
^
I'm guessing this is because there is a possible return type of Unit because the value of n could meet none of the conditions?
In Java "if-else" is a statement. In Scala it is an expression (think of Java's ternary ?:), meaning that it always produces some value. As mentioned by som-snytt in comments, in case of a missing else block the compiler supplies else (), which is of type Unit, which obviously conflicts with the expected type Double in your example.
Some valid examples of missing else are provided in Chris's answer.
No - In general, an if expression does not require an else clause.
Examples:
if (true) println("a")
// prints "a"
if (false) println("a") else if (true) println("b")
// prints "b"
As Nikita Volkov's answer says, though, it is necessary if you need the expression to have some type other than Unit.
Your guess is correct. The method must return a Double, yours would return Unit if non of the "if.." cases match. Actually, when you paste the second definition into the repl, you should get
<console>:11: error: type mismatch;
found : Unit
required: Double