Infinite loop seems to confuse Scala's type system - scala

Here is an artificial toy example that demonstrates my problem:
def sscce(): Int = {
val rand = new Random()
var count = 0
while (true) { // type mismatch; found: Unit, required: Int
count += 1
if (rand.nextInt() == 42) return count
}
}
How can I help the compiler understand that this method will always return an Int?
I know the above toy example could easily be refactored to get rid of the infinite loop altogether, but I really want to have the infinite loop in my actual code. Trust me on this ;)

Always return an Int:
def sscce(): Int = {
val rand = new Random()
var count = 0
while (true) {
count += 1
if (rand.nextInt() == 42) return count
}
count // <-- this
}

You can also do:
def foo: Int = {
...
while(true) {
... return ...
}
throw new IllegalStateException // unreachable
}
this will typecheck because the type of the throw is Nothing, which is a subtype of Int.

See this question. While loops don't return a value. i.e. they return Unit which is the last statement in your function. So, the definition says it returns an Int but it actually returns Unit thus the type error. #ionut's answer fixes the type error by returning count as the last statement or here is a recursive approach.
def sscce(): Int = {
val rand = new Random()
def ssccer(count: Int): Int = {
if(rand.nextInt == 42) return count
else ssccer(count + 1)
}
ssccer(0)
}

Per the SLS, a while loop is executed similarly to:
def whileLoop(cond: => Boolean)(body: => Unit): Unit =
if (cond) { body ; whileLoop(cond)(body) } else {}
ie., it returns Unit. So the compiler sees the while as the last statement in sscce(), and therefore assumes that you're trying to return Unit. I don't think it's smart enough to realize that return count will eventually always return an Int.
The simple solution is to follow the suggestion of #Brian or #IonutGStan, and force it to return count, whether it truly needs it or not.

From a code quality standpoint, it would be good to ditch the while(true) loop and replace it with something more readable. As a nice side effect, it also solves your problem:
def sscce(): Int = {
val rand = new Random()
var count = 1
while (rand.nextInt() != 42) {
count += 1
}
count
}

Related

Scala accessing variable outside function

I was reading an article at https://medium.com/#aarshkshah1992/scala-functional-memoization-and-lazy-loading-caches-de116f24828
and this part is really interesting
def memoizedIsPrime: Int => Boolean = {
def checkIfPrime(i: Int): Boolean = {
2 to (i - 1) forall (x => i % x != 0)
}
var cache = Map.empty[Int, Boolean]
i => {
if (!cache.contains(i)) {
print(s"Calling isPrime since input ${i} has not been seen before and caching the output")
cache = cache updated(i, checkIfPrime(i))
}
else print(s"Input ${i} has been seen before , returning cached output")
cache(i)
}
}
val isPrime = memoizedIsPrime
Can anyone explain how i is being accessed and the how the code part after => is really working?
Thanks in advance :)
The result of memoizedIsPrime is Int => Boolean, in other words a function that takes an Int and returns a Boolean.
So in the body of the code, after we get some preliminary def and val definitions out of the way, we need a way to reference the incoming Int:
i => ...
OK, so it is decided, we'll refer to the received Int as i. Now we need to produce a Boolean value. And that, of course, is the { } delimited block of code that comes after the => which gets executed every time a new Int arrives.

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.

Why is my function returning a Unit instead of Int?

I am new to Scala and working on a project. I am writing a function that is suppose to return the smallest Int in an array. However when I run it I get a type error that it is returning unit instead of int.
Here is my code:
def minWhile(r: Array[Int]): Int = {
var pos = 1
var minInt = r(0)
while (pos < r.length) {
if (r(pos) < minInt)
minInt = r(pos)
pos += 1
}
minInt
}
Thank you very much!
Your code is compiled correctly, because it always returns correct type Int. But it may cause some runtime exceptions, if we passed empty array into your function: minWhile(Array()).
def minWhile(r: Array[Int]): Int =
{
var pos = 1
var minInt = r(0) /* potential runtime exception */
while( pos < r.length){
if(r(pos) < minInt)
minInt = r(pos)
pos+=1
}
minInt
}
You have to check arrays bounds working with it.
Or you can use a shorter way:
def minWhile(r: Array[Int]): Option[Int] = if (r.nonEmpty) Some(r.min) else None
Your code should be compiled correctly but it may rise an exception when passed empty container. You are using variables which is discouraged.
I would do it using some recursion calls or scala collections API like so:
array.reduceLeft(a: Somehitng, b: Something => Something)
Check thia link:
http://m.alvinalexander.com/scala/scala-use-reduceleft-get-max-min-from-collection
Consider this more functional style of conveying the semantics of minWhile, as follows,
def minWhile(r: Array[Int]): Int = {
(r zip r.drop(1)).takeWhile(t => t._1 > t._2).last._2
}
where we zip consecutive items and take those monotonically decreasing. The desired result is found in the second part of the last duple.

How to tell the Scala compiler that a while loop will return a value?

Some algorithms execute a while loop with condition true and will (for sure) end at some point with a return statement inside the body of the while loop. E.g.:
def foo: Int = {
while(true) {
// At some time, the while loop will do a return statement inside its body
if( ... )
return 0
}
}
Simple example (without semantic sense):
def foo: Int = {
var i = 0
while(true) {
i += 1
if(i == 10)
return 0
}
}
The Scala compiler complains about a type mismatch, because the while loop has type Unit and the compiler does not know, that the while loop will at some point return a value. We could fix this with a workaround like:
def foo: Int = {
var i = 0
while(true) {
i += 1
if(i == 10)
return 0
}
0 // !
}
But this looks ugly. Is there a better workaround ? Or even a better solution for this kind of problem ?
You could throw an exception:
def foo: Int = {
var i = 0
while(true) {
i += 1
if(i == 10)
return 0
}
throw new IllegalStateException("This should never happen")
}
The compiler will stop complaining about the type mismatch, and since the while loop always returns something, the exception will never be thrown. And if it is, you will quickly find out where you did something wrong :).
There are other ways to write this loop which are more idomatic and Scala-esque, but given the code you provided, this will get the job done in a clear and simple way.
Maybe you should just use tail recursion instead. It should end up compiling down to very similar bytecode:
import scala.annotation.tailrec
def foo: Int = {
#tailrec def bar(i: Int): Int = {
val j = i + 1
if (j == 10) return 0
else bar(j)
}
bar(0)
}
You might even want to make use of the default parameter value support:
#tailrec def foo(i: Int = 0): Int = {
val j = i + 1
if (j == 10) return 0
else foo(j)
}
Note that this way requires you to call the function as foo() not foo since it has an argument.
A more idiomatic way would be to use recursion. Something like this:
def foo: Int = {
import scala.annotation.tailrec
#tailrec def whileUnderTen(i: Int):Int = if ( i < 10) whileUnderTen(i+1) else 0
whileUnderTen(0)
}
For just these occasions, I have a "forever" construct defined in my personal standard library.
forever{
}
is in all ways equivalent to
while(true){
}
except that forever has type Nothing while the equivalent while construct has type Unit. Just one of those small extension capabilities that makes Scala such a joy.

foreach in method to return value

def a: Int = {
for(i <- Array(1,2,3,4,5)){
if(i == 3)
return i
}
}
The above method will not compile, I get the following error:
error: type mismatch;
found : Unit
required: Int
for(i <- Array(1,2,3,4,5)){
^
The expected behaviour is that the method returns 3. What is wrong with my code?
That is because your lambda in the foreach does guarantee to return a value. If you provide a default return value it should work.
def a: Int = {
for(i <- Array(1,2,3,4,5)){
if(i == 3)
return i
}
0
}
It's because there is no else or a default return value.
If a method has return type Int, than all paths in that method must return an Int. This is not the case in your implementation. For example, if in the Array there would not be the number 3, nothing would be returned, which means the return type would be Unit.
Don't Use Return in #Scala .
The return keyword is not “optional” or “inferred”; it changes the meaning of your program, and you should never use it.
https://tpolecat.github.io/2014/05/09/return.html