Don't Use Return in Scala?

Let’s revisit what you’ve said earlier:

I have:

  • removed arms of control flow
  • made it clear which variables are in scope (all are to the left of <- operator in for comprehension)
  • replaced everything with for comprehension

I don’t see a difference about shadowing. There’s the same number of variables in scope in every approach.

Every line required either nestError or returnEarly, but:

  • in case of nested flatMaps I need flatMap for every nest level (i.e. every Either)
  • in case of magical ? operator I need to insert that operator for every Either - I could rename nestError to ? if that operator is so cool
  • if you forget to do either nestError or returnEarly on some line then resultNested.joinLeft won’t compile, so you’ll immediately know you’ve forgot something

Also, you’ve forgot to wrap results in Right, i.e. there should be return Right(Response(... instead of return Response(...

After renaming nestError to ? the contest would be between hypothetical:

def handleTransfer(req: TransferRequest): Either[Err, Response] = {
  val u1 = req.user1.lookup(db).?
  val u2 = req.user2.lookup(db) match {
    case Left(e) => return Right(Response(s"Cannot find ${req.user2}: $e"))
    case Right(u) => u
  }
  val depositor = u2.checkAccess(u1) match {
    case Left(e) => return Right(Result(s"$u2 has not given you deposit access"))
    case Right(dep) => dep
  }
  val withdrawal = u1.withdraw(req.amount).?
  val conf = depositor.accept(withdrawal).?
  Result(s"You transferred $withdrawal to $u2, confirmation number $conf")
}

and already working:

  def handleTransfer(req: TransferRequest): Either[Err, Result] = {
    for {
      u1 <- req.user1.lookup(db).?
      u2 <- req.user2.lookup(db).earlyResult { e =>
        Result(s"Cannot find ${req.user2}: $e")
      }
      depositor <- u2.checkAccess(u1).earlyResult { _ =>
        Result(s"$u2 has not given you deposit access")
      }
      withdrawal <- u1.withdraw(req.amount).?
      conf <- depositor.accept(withdrawal).?
    } yield {
      Result(s"You transferred $withdrawal to $u2, confirmation number $conf")
    }
  }.joinLeft
1 Like