This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Scala immutable variables and printing
I am confused why this will not run as i expect it to, I have tried to change it multiple times and it still give an error stating that it is given Unit and needs Int.
def div(m: Int, n: Int): Int = {
var counter = 0
var p = m
while (p >= 0) {
p -= n
counter += 1
println(counter)
}
}
In scala result of last operation would be return value. In your piece of code last operation is while loop that doesn't return anything (or, if you want, return Unit which is the same as nothing) while you specified return value of Int.
So if you need to return value of p write this:
def div(m: Int, n: Int): Int = {
var counter = 0
var p = m
while (p >= 0) {
p -= n
counter += 1
println(counter)
}
p
}
In Scala function returns result of the last expression. Last expression of your "div"-function is the while-loop, which returns no value, so the type of result in your function is Unit ("void" in Java)
Related
So i have code in xcode playground and got the error error in code
and this is the excercise i do
Return the Factorial
Create a function that takes an integer and returns the factorial of that integer. That is, the integer multiplied by all positive lower integers.
and this is my code
func factorial(_ num: Int) -> Int {
var result :Int = 0
for _ in num...1 {
result = num * (num - 1)
}
return result
}
print(factorial(12)) //error in this line
but in terminal got this output:
The answer is in the error message - the upper bound of the range has to be greater than or equal to the lower.
Therefore you'll need to rewrite the method differently. You also have a fundamental flaw in your code - your maths logic is wrong - result will be overwritten every time, rather than accumulating a total. Adopting a similar approach to the question you can do this:
func factorial(_ num: Int) -> Int {
var result :Int = 1
guard num > 0 else {return result}. //0! is 1 not 0
var num = num
while num > 0 {
result *= num
num -= 1
}
return result
}
There is a more elegant way of performing this using recursion, which avoids the ugly var num=num
func fac2(_ num: Int, total: Int = 1) -> Int {
return num > 0 ? fac2(num-1, total: total * num) : total
}
I am editing following code in eclipse but it complains that "recursive method loop needs result type", so what's the error? Thanks.
package week2
object exercise {
def factorial(n: Int): Int = {
def loop(acc: Int, n: Int) =
if (n == 0) acc
else loop(acc * n, n - 1)
loop(1, n)
}
factorial(4)
}
Thanks for the answer. Yes, I missed something here. The correct is:
package week2
object exercise {
def factorial(n: Int): Int = {
def loop(acc: Int, n: Int): Int =
if (n == 0) acc
else loop(acc * n, n - 1)
loop(1, n)
} //> factorial: (n: Int)Int
factorial(4) //> res0: Int = 24
}
As sepp2k indicated, it's restricted by compiler. Just wanted to add more info for clarification.
According to Scala's local type inference mechanism
return types of methods can often be omitted since they correspond to the type of the body, which gets inferred by the compiler
Consider non-recursive function
def f(n: Int) = n % 2 == 0
where compiler can infer a result type, since it knows that expression x % 2 == 0 will always produce type Boolean.
But when you deal with a recursive function, like
def f(n: Int) = if (n == 0) 1 else n * f(n-1)
Scala compiler won't infer the result type of if (x == 0) 1 else x * f(x-1) since that leads to an infinite loop. It can't even know that f(x-1) is an eligible operand for * operation, thus will give you an error Cannot resolve reference * with such signature.
The rules of the Scala language that any recursive method needs to be declared with a return type. loop is a recursive method and you didn't declare a return type for it (you only declared one for factorial, which doesn't necessarily need one). Therefore scalac (and by extension Eclipse) is telling you that the recursive method loop needs a return type.
Why does the method give a compile error in NetBeans
( error in question -- Type Mismatch Found Unit : required Array[Int] )
def createArray(n:Int):Array[Int] =
{
var x = new Array[Int](n)
for(i <- 0 to x.length-1)
x(i) = scala.util.Random.nextInt(n)
}
I know that if there was a if clause - and no else clause - then why we get the type mismatch.
However, I am unable to resolve this above error - unless I add this line
return x
The error is not happening because the compiler thinks what happens if n <= 0
I tried writing the function with n = 10 as hardcoded
Thoughts ?
Your for comprehension will be converted into something like:
0.to(x.length - 1).foreach(i => x(i) = scala.util.Random.nextInt(i))
Since foreach returns (), the result of your for comprehension is (), so the result of the entire function is () since it is the last expression.
You need to return the array x instead:
for(i <- 0 to x.length-1)
x(i) = scala.util.Random.nextInt(n)
x
Yet another one,
def createArray(n: Int): Array[Int] = Array.fill(n) { scala.util.Random.nextInt(n) }
Then, for instance
val x: Array[Int] = createArray(10)
You could do something cleaner in my own opinion using yield :
def createArray(n:Int):Array[Int] =
(for(i: Int <- 0 to n-1) yield scala.util.Random.nextInt(n)).toArray
This will make a "one lined function"
Simple scala question. Consider the below.
scala> var mycounter: Int = 0;
mycounter: Int = 0
scala> mycounter += 1
scala> mycounter
res1: Int = 1
In the second statement I increment my counter. But nothing is returned. How do I increment and return something in one statement.
Using '+=' return Unit, so you should do:
{ mycounter += 1; mycounter }
You can too do the trick using a closure (as function parameters are val):
scala> var x = 1
x: Int = 1
scala> def f(y: Int) = { x += y; x}
f: (y: Int)Int
scala> f(1)
res5: Int = 2
scala> f(5)
res6: Int = 7
scala> x
res7: Int = 7
BTW, you might consider using an immutable value instead, and embrace this programming style, then all your statements will return something ;)
Sometimes I do this:
val nextId = { var i = 0; () => { i += 1; i} }
println(nextId()) //> 1
println(nextId()) //> 2
Might not work for you if you need sometime to access the value without incrementing.
Assignment is an expression that is evaluated to Unit. Reasoning behind it can be found here: What is the motivation for Scala assignment evaluating to Unit rather than the value assigned?
In Scala this is usually not a problem because there probably is a different construct for the problem you are solving.
I don't know your exact use case, but if you want to use the incrementation it might be in the following form:
(1 to 10).foreach { i =>
// do something with i
}
I'm doing some revision for an upcoming repeat :( and I've run into a problem with the following recursive implementation of Selection Sort in Scala.
For the most part this works, but it doesn't seem to be swapping the first two values when they should be swapped. I'm sure it's pretty basic but my problem solving cap is a little rusty at this stage
Any ideas greatly appreciated, here is the code I have so far:
object question3 {
def main(args : Array[String]) : Unit =
{
var arr = Array(8,9,8,5,2,4,1,6,3,7,5,-1,5,0,99)
arr = sort(arr, 0, 0, 0)
println("RESULT:")
arr.foreach(str=>print(str+","))
}
def sort(arr : Array[Int], n : Int, min : Int, j : Int): Array[Int] =
{
if(n == arr.length)
{
return arr
}
else
{
var j = n+1
var min = n
if(j < arr.length)
{
if(arr(j) < arr(min))
{
min = j
}
sort(arr, n+1, min, j+1)
}
if(min != n)
{
var t = arr(n)
arr(n) = arr(min)
arr(min) = t
}
sort(arr, n+1, min, j)
}
}
}
First, you never use the min and j parameters for anything, instead shadowing them with local definitions.
Second, you should not set the min variable until after the first recursive call. As your code stands, it sets min according to which of the first two initial elements is smaller, but never considers the possibility that there's an even smaller one later in the array.
This gives something that looks more like an attempt at bubblesort than selection sort. If you want true selection sort you probably want a sepearate loop (or recursive function) to find the index of the minimal element first.