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
Related
I've been working on the scala recursion problem. I used to develop the program using loops and then use the concept of recursion to convert the existing loop problem in a recursive solution.
So I have written the following code to find the perfect number using loops.
def isPerfect(n: Int): Boolean = {
var sum = 1
// Find all divisors and add them
var i = 2
while ( {
i * i <= n
}) {
if (n % i == 0) if (i * i != n) sum = sum + i + n / i
else sum = sum + i
i += 1
}
// If sum of divisors is equal to
// n, then n is a perfect number
if (sum == n && n != 1) return true
false
}
Here is my attempt to convert it into a recursive solution. But I'm getting the incorrect result.
def isPerfect(n: Int): Boolean = {
var sum = 1
// Find all divisors and add them
var i = 2
def loop(i:Int, n:Int): Any ={
if(n%i == 0) if (i * i != n) return sum + i + n / i
else
return loop(i+1, sum+i)
}
val sum_ = loop(2, n)
// If sum of divisors is equal to
// n, then n is a perfect number
if (sum_ == n && n != 1) return true
false
}
Thank you in advance.
Here is a tail-recursive solution
def isPerfectNumber(n: Int): Boolean = {
#tailrec def loop(d: Int, acc: List[Int]): List[Int] = {
if (d == 1) 1 :: acc
else if (n % d == 0) loop(d - 1, d :: acc)
else loop(d - 1, acc)
}
loop(n-1, Nil).sum == n
}
As a side-note, functions that have side-effects such as state mutation scoped locally are still considered pure functions as long as the mutation is not visible externally, hence having while loops in such functions might be acceptable.
I am trying to use placeholder syntax for simple map:
Array(1,2,3).map(if(_ % 2 == 0) _ * 2)
I was expecting to have the same effect as:
Array(1,2,3).map(i=>if (i%2==0) i * 2)
It complains
error: type mismatch;
found : Unit
required: Int => ?
I also tried:
Array(1,2,3).map(if(_ % 2 == 0) _ * 2 else _) //with else
Array(1,2,3).map(if((_:Int) % 2 == 0) (_:Int) * 2 else (_:Int)) //All typed
Array(1,2,3).map(if((_:Int) % 2 == 0) 0 else 1) //Typed and specific return Int
Every one of them gives error. How to properly use this syntax in this case?
Edit
The link states that filter(_:Boolean) and filter (_ == true) should work, but my trials with specific typing does not work. This link also states that if (_) x else y should work, but in my case it does not. Need more explanation.
Edit 2
Tried:
Array(true,false).map(if(_) 0 else 1)
It works. But my case:
Array(1,2,3).map(if((_) % 2 == 0) 0 else 1)
Does not work.
Does this syntax only support such simple expressions?
Re: your original question:
Array(1, 2, 3).map(if (_ % 2 == 0) _ * 2)
// error: missing parameter type for expanded function ...
// error: type mismatch ...
The _ placeholder used in such pattern represents positional parameters of an anonymous function, hence if (_ % 2 == 0) _ * 2 is equivalent to:
if (x => x % 2 == 0) y => y * 2
That explains the missing parameter error. The type mismatch error is due to missing else in the if statement, forcing the compiler to return a Unit:
Array(1, 2, 3).map(i => if (i % 2 == 0) i * 2 else i)
// res1: Array[Int] = Array(1, 4, 3
Given that you need to specify the single input multiple times I'm not sure it'll work for you.
As you've already noticed, this placeholder syntax does have its limitation and should be treated as a convenient shortform for relatively simple cases. Like the if (_ % 2 == 0) 0 else 1) case, nesting _ within a map generally does not work well. For example:
List("a", "b", "c").map(_ * 3)
// res2: List[String] = List(aaa, bbb, ccc)
List("a", "b", "c").map((_ + " ") * 3)
// error: missing parameter type for expanded function ...
For more usage re: _, here is a SO link, and a Scala doc about commonly used symbols including _.
I tried to write a function for fast power in scala, but I keep getting java.lang.StackOverflowError. I think it has something to do with two slashes that use in the third line when I recursively called this function for n/2.
Can someone explain why is this happening
def fast_power(x:Double, n:Int):Double = {
if(n % 2 == 0 && n > 1)
fast_power(x, n/2) * fast_power(x, n /2)
else if(n % 2 == 1 && n > 1)
x * fast_power(x, n - 1)
else if(n == 0) 1
else 1 / fast_power(x, n)
}
Your code doesn't terminate, because there was no case for n = 1.
Moreover, your fast_power has linear runtime.
If you write it down like this instead:
def fast_power(x:Double, n:Int):Double = {
if(n < 0) {
1 / fast_power(x, -n)
} else if (n == 0) {
1.0
} else if (n == 1) {
x
} else if (n % 2 == 0) {
val s = fast_power(x, n / 2)
s * s
} else {
val s = fast_power(x, n / 2)
x * s * s
}
}
then it is immediately obvious that the runtime is logarithmic, because
n is at least halved in every recursive invocation.
I don't have any strong opinions on if-vs-match, so I just sorted all the cases in ascending order.
Prefer the match construct instead of multiple if/else blocks. This will help you isolate the problem you have (wrong recursive call), and write more understandable recursive functions. Always put the termination conditions first.
def fastPower(x:Double, m:Int):Double = m match {
case 0 => 1
case 1 => x
case n if n%2 == 0 => fastPower(x, n/2) * fastPower(x, n/2)
case n => x * fastPower(x, n - 1)
}
I'm trying to figure out this compile error:
Error:(51, 4) identifier expected but '}' found.
} else if (n < 0) {
^
For this code:
def nthPowerOfX(n: Int, x:Double) : Double = {
if (n == 0) {
1.0
} else if (n < 0) {
1.0 / nthPowerOfX(n,x)
} else if (n % 2 == 0 && n > 0) {
nthPowerOfX(2, nthPowerOfX(n/2,x))
} else {
x*nthPowerOfX(n-1, x)
}
}
I tried return statements too but that didn't help nor should it matter to my understanding.
Jozef is right! There is no error. Please consider using this:
def nthPowerOfX(n: Int, x:Double) : Double = {
n match{
case 0 => 1.0
case x if x < 0 => 1.0 / nthPowerOfX(n,x)
case x if x % 2 == 0 && x > 0 => nthPowerOfX(2, nthPowerOfX(n/2,x))
case x => x*nthPowerOfX(n-1, x)
}
}
But keep in mind that recursion is dangerous thing, it's better to use tail recursion, if we are talking about Scala.
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