Reputation: 1159
I have a function which returns a Double => String
function in Scala. When I add the return
s at the end of the function, I get a type mismatch
:
type mismatch; found : String required: Double ⇒ String
Why is this the case? Isn't return
purely optional in Scala? In this scenario, everything is fine when I delete the two return
s, but what would I do if I wanted to return somewhere before that if/else?
def createBuckets(start: Double, end: Double, gap: Double): Double => String = {
var buckets: List[String] = List[String]()
val endPoints: List[Double] = List[Double]()
var first = start
var second = gap
while (second < end) {
buckets ::= first + " to " + second
first = second
second += gap
}
if (first != end) {
buckets ::= first + " to " + end
}
buckets = buckets.reverse
println("BUCKETS: " + buckets)
val range = end - start
(input: Double) => {
val bucket = (input / gap).floor.toInt
if (input == end) {
// Type mismatch from this return
return buckets(buckets.size - 1)
} else {
// and this one
return buckets(bucket)
}
}
}
Upvotes: 0
Views: 1368
Reputation: 16324
Here is a simplified version of your error:
def foo: Int => Int = { x => return x } //error
Note that return
is only used in methods definitions. It is not usually valid in anonymous functions. This syntactic error is clearer if you try declaring a val
instead:
val foo: Int => Int = { x => return x }
//error: return outside method definition
You can read more about the difference between methods and functions here.
Even in method bodies, return
is almost always unidiomatic in Scala, and is generally avoided. If you want to return before the final if-else
, you can wrap the whole block in another if-else
, or instantiate a val
and make the last statement of the expression the val
(e.g. { val x = 5; ...; x }
).
Upvotes: 3
Reputation: 39577
If for some reason a return was called for:
def outer(): Int => String = {
def f(i: Int): String = { if (i < 0) return "BAD" ; "hello" take i }
f
}
Your only hangup is that you want to return a function with minimal boilerplate.
This is just a compiler bug, but it's pretty funny:
object X { def f(i: Int = return 42) = i * 2 }
Upvotes: 3
Reputation: 4761
return
returns from your def
, not your anonymous function. Hence the type error. Now, as stated in other answers, in your case you could simply remove it:
if (input == end) {
buckets(buckets.size - 1)
} else {
// and this one
buckets(bucket)
}
You don't need early return statements, and in general you can structure any code to have a single return point.
For example a common pattern in imperative languages:
def sillyExample(input) {
if (input.isBad) {
return None
}
//some complex operations go here
return Some(complexResult);
}
This can be rewritten as:
def sillyExample(input) {
if (input.isBad) {
None
} else {
//some complex operations go here
Some(complexResult);
}
}
That is no more complex. The extra level of indentation for the happy-path code can be annoying (and can be solved by higher functional abstractions but I digress), but you get used to it very quickly. The advantage on not having arbitrary return
statements, and focusing on expressions instead is that it brings you a step closer to referential transparency
Upvotes: 2
Reputation: 125
You should remove the return keywords because they forcefully return a result from the createBuckets function and you get a type mismatch error because the returned type is a String (the bucket), not a function from Double to String. Using the return keyword is not idiomatic scala and you should try to avoid it. I hope this helps.
Upvotes: 1