Consider the following example
def futureFoo() = {
Future.successful(true)
}
def recFoo(x: List[Int]): Unit = {
if (x.isEmpty) return
for {
b <- futureFoo()
v = getNewListOfValues(x.last)
_ = recFoo(v)
} yield b
}
I need to wait for futureFoo
to finish and only then call recFoo
again. The problem is no matter what I try I get the following error:
discarded non-Unit value
I also tried to convert it into a while loop but because of the future I either get the same error or the while condition doesn't update because it must be updated in a for comprehension
or map
.
Any ideas on how to prevent that error?
CodePudding user response:
Try this.
def recFoo(x: List[Int]): Unit =
if (x.nonEmpty)
futureFoo().foreach(_ => recFoo(getNewListOfValues(x.last)))
CodePudding user response:
The specific reason that you are getting
discarded non-Unit value
in your error message is that you have an expression after return
.
Note that in Scala, the return
keyword should almost never be used. Scala is an expression-oriented language; each block (such as a function body) evaluates to the value returned from the last line in the block.
So, for example, consider the following snippet:
val foo = {
import scala.util.Random
if (Random.nextInt() % 2 == 0) {
17
} else {
"bar"
}
}
Everything from if
to the closing brace after "bar"
is a single expression -- NOT a statement. Scala, in face, does not have "if-statements" in the way that Java and other languages do. In particular, the compiler needs to infer a type for the name foo
, and since foo
could concretely be either the Int
17
or the String
"bar"
, that inferred type is the closest common ancestor of both Int
and String
, which is Any
.
In your question, the last expression in the body of recFoo
is the following:
for {
b <- futureFoo()
v = getNewListOfValues(x.last)
_ = recFoo(v)
} yield b
What is the type of this expression? In many languages, for
introduces a statement, but that's not true of Scala -- this is an expression, not a statement, and like all expressions it will have a value once we evaluate it. That value has type Future[Unit]
, and like all non-Unit
values, the compiler is warning you that you are discarding a value, which is (almost) always a mistake. (Why would you go to the trouble of producing a non-Unit
value and then not make use of it?, goes the thinking.)