问题
I am learning Scala at the moment. One thing that I like to do is early returns. I'm convinced that this is far easier for everyone to read as we just remove the invalid states before. Now, as Scala is a functional language and I've read that cutting computation is bad functional style, I'm wondering if there is some trick or functional programming equivalent to early return.
This is code I would write, to be completely clear, this is just a dumb example, I'm not looking for the special hack of my special case, but more for a general advice on how to deal with these.
if (request.headers.get(session_header).isEmpty) {
BadRequest(session_not_set)
} else {
Ok(CartHelper.getCart(session, user))
}
Now, what I'm tempted to do is:
if (request.headers.get(session_header).isEmpty) {
BadRequest(session_not_set)
return;
}
Ok(CartHelper.getCart(session,user))
If you have any hint for me!
回答1:
In some instances the return
keyword cannot be avoided, but it doesn't look like you have that problem currently.
Scenario 1: The single condition scenario, your current one. In this instance you can avoid using return
with a very simple if else
.
def doSomething: AnyContent = {
if (request.headers.get(session_header).isEmpty) {
BadRequest(session_not_set)
} else {
Ok(CartHelper.getCart(session,user))
}
}
If the session not being set is a common problem, you can simply have a guard around it with a partial function.
def requireSession(req: Request)(
pf: Session => AnyContent
): AnyContent = {
request.headers.get(session_header)
.fold(BadRequest("Session not set"))(pf(_))
}
And then:
// Assuming Play framework being used here
def getCart: AnyContent = Action { implicit req =>
requireSession(req) { session => Ok(CartHelper.getCart(session, user) }
}
Scenario 2: Break loop using return, or the so called early return is usually a performance improvement element.
One apparently valid use of return
in Scala which is something that seems unavoidable is a situation where you are iterating a collection for the first of something. Obviously you can have that abstracted away for you using collection.find
and other helper methods pre-build in the standard lib, but for the sake of argument.
def inList[T](l: List[T], value: T): Boolean = {
for (el <- l) {
// break the loop for the first match found
// for the sake of efficiency.
if (el == value) return true;
}
false;
}
Even in situations like this return
is avoidable, by using a different construct, and there's always a recursive version of something you can use to replace an apparently impossible return
inside dan iteration.
来源:https://stackoverflow.com/questions/38833876/how-to-early-return-in-scala