Either for validation in Scala
Either keeps the reason a value was rejected, where a bare Option cannot.
// Either carries a failure on the Left and a success on the Right,
// so the reason for a rejection survives the return trip.
case class Booking(guest: String, nights: Int)
def validate(guest: String, nights: Int): Either[String, Booking] =
if guest.isEmpty then Left("guest name is required")
else if nights < 1 then Left(s"$nights nights is not a stay")
else if nights > 30 then Left("stays over 30 nights need approval")
else Right(Booking(guest, nights))
// Matching both sides means no failure can be quietly dropped.
def confirm(guest: String, nights: Int): String =
validate(guest, nights) match
case Right(booking) => s"booked ${booking.guest} for ${booking.nights}"
case Left(problem) => s"rejected: $problem"
// map and getOrElse act on the Right side and leave a Left untouched.
def nightsOrZero(guest: String, nights: Int): Int =
validate(guest, nights).map(_.nights).getOrElse(0)
How it works
validatereturns aLeftholding the message, orRight(Booking(guest, nights))when every rule passes.- The match names both sides,
case Right(booking)andcase Left(problem), so no failure is dropped. validate(guest, nights).map(_.nights)acts on the Right side only and leaves a Left alone.
Keywords and builtins used here
BookingEitherIntLeftRightStringcaseclassconfirmdefelseifmatchnightsOrZerothenvalidate
The run, in numbers
- Lines
- 19
- Characters to type
- 897
- Tokens
- 162
- Three-star pace
- 70 tpm
At the three-star pace of 70 tokens a minute, this run takes about 139 seconds.
Step 3 of 3 in Option & Either, step 21 of 27 in Language basics.