Return a User if it exists, otherwise inserting if email address Option is present - scala

If I have an email, I want to either get the user by email if it exists. If it doesn't exist, I want to insert and return the User.
val userOptFut: Future[Option[User] = emailOpt.map { email =>
userDao.getByEmail(email).map { maybeUserFut =>
maybeUserFut match {
case Some(u) => Future.successful(Some(u))
case None =>
userDao.insert(User(....)) // Future[User]
}
}
}.getOrElse(Future.successful(None))
Where userDao.getByEmail(..) returns Future[Option[User]]
I am not sure what is wrong, but for some reason it says I am return a Object and not a User.
expression of type Future[Object] does not conform to expected type
Future[Option[User]]
What is wrong with the above?

It's really difficult with nesting like that to match the types up correctly everywhere. What the compiler ends up doing is inferring the most specific type it can, which is Object, and that doesn't match your declared types.
It really helps to break down your functions into smaller pieces, with fewer levels of nesting, so the types are much more difficult to mess up. I would do it something like the following:
// This is very close to Future.sequence, but Option isn't a subclass
// of TraversableOnce. There's probably an existing function to do
// this in a library like cats or scalaz.
def toFutureOption[A](in: Option[Future[A]]): Future[Option[A]] = in match {
case Some(fut) => fut map {Some(_)}
case None => Future.successful(None)
}
def getOrInsert(email: String): Future[User] =
userDao.getByEmail(email) transformWith {
case Success(Some(user)) => Future.successful(user)
case Success(None) | Failure(_) => userDao.insert(User(email))
}
val userOptFut: Future[Option[User]] =
toFutureOption(emailOpt map getOrInsert)

Your problem is that the two branches of your match statement don't return the same type:
case Some(u) => u // User
case None => userDao.insert(User(....)) // Future[User]
Depending on what you are trying to achieve, you could do something like this:
case Some(u) => Future.successful(Some(u))
The .getOrElse at the end may not be suitable for your type either.

Related

How to use a Result[String] in Scala match expression

In the following code the first expression returns a Result[String] which contains one of the strings "medical", "dental" or "pharmacy" inside of a Result. I can add .toOption.get to the end of the val statement to get the String, but is there a better way to use the Result? Without the .toOption.get, the code will not compile.
val service = element("h2").containingAnywhere("claim details").fullText()
service match {
case "medical" => extractMedicalClaim
case "dental" => extractDentalClaim
case "pharmacy" => extractPharmacyClaim
}
Hard to say without knowing what Result is. If it's a case class, with the target String as part of its constructor, then you could pattern match directly.
Something like this.
service match {
case Result("medical") => extractMedicalClaim
case Result("dental") => extractDentalClaim
case Result("pharmacy") => extractPharmacyClaim
case _ => // default result
}
If the Result class doesn't have an extractor (the upapply() method) you might be able to add one just for this purpose.
I'm assuming this Result[T] class has a toOption method which returns an Option[T] - if that's the case, you can call toOption and match on that option:
val service = element("h2").containingAnywhere("claim details").fullText().toOption
service match {
case Some("medical") => extractMedicalClaim
case Some("dental") => extractDentalClaim
case Some("pharmacy") => extractPharmacyClaim
case None => // handle the case where the result was empty
}

Is there a way to match everything but a certain type (or set of types) without using isInstnaceOf?

I know that you can match a set of types like so, without using isInstanceOf:
x match {
case fooBar # (_: Foo | _: Bar) => ???
}
But, is there a way to match anything but a set of types? Like, match any x which is not a Foo or a Bar, without using isInstanceOf?
Well, you can do
x match {
case fooBar #(_: Foo | _: Bar) => // do nothing
default => // do something
}
Anyway, the only difference with using isInstanceOf is syntax, as you will be performing a runtime check nonetheless.
From a functional point of view, the combo isInstanceOf/asInstanceOf is identical to type matching.
So (if you really must) I would just go with
if (!(x.isInstanceOf[Foo] || x.isInstanceOf[Bar])) {
// do something
}
Again, there's no practical difference and they're both quite a hacky way of dealing with types. Unless you're working with an external API you have not control over, I would suggest to change your design and avoid matching on the types.
Usually type classes come in handy, but without further details it's hard to tell for sure.
The solution above by #GabrielePetronella work well for most cases, but I'm adding another variant that can help with some edge cases.
Edge case example:
composed Receive functions for akka actors.
consider the following:
override def receive: Receive = handleFoo orElse handleBar
def handleFoo: Receive = {
case FooObject => …
case FooClass(value) => …
case notFoo =>
logger.debug(s"wasn't expecting $notFoo of type ${notFoo.getClass.getSimpleName}")
}
def handleBar: Receive = {
case _: VeryImportantBarMsg => …
case _: LessImportantBarMsg => …
}
The last case of handleFoo will catch everything, making the orElse handleBar obsolete, and obviously we don't handle VeryImportantBarMsg or LessImportantBarMsg any more.
Solution:
use a specialized extractor object, e.g:
object NotBar {
def unapply[T](t: T): Option[T] = t match {
case _: VeryImportantBarMsg | _: LessImportantBarMsg => None
case _ => Some(t)
}
}
and use it like:
def handleFoo: Receive = {
case FooObject => …
case FooClass(value) => …
case NotBar(notFoo) =>
logger.debug(s"wasn't expecting $notFoo of type ${notFoo.getClass.getSimpleName}")
}
This solution is intended for case where you don't want the match to succeed, like partial functions, akka receive, or if you find yourself writing the same excluded list of types _: T1 | … | _: T10 many times, etc'...
P.S.
If you find yourself in need of this solution, most likely something isn't modeled optimally. In most cases, this can be avoided.

Cleanest way in Scala to avoid nested ifs when transforming collections and checking for error conditions in each step

I have some code for validating ip addresses that looks like the following:
sealed abstract class Result
case object Valid extends Result
case class Malformatted(val invalid: Iterable[IpConfig]) extends Result
case class Duplicates(val dups: Iterable[Inet4Address]) extends Result
case class Unavailable(val taken: Iterable[Inet4Address]) extends Result
def result(ipConfigs: Iterable[IpConfig]): Result = {
val invalidIpConfigs: Iterable[IpConfig] =
ipConfigs.filterNot(ipConfig => {
(isValidIpv4(ipConfig.address)
&& isValidIpv4(ipConfig.gateway))
})
if (!invalidIpConfigs.isEmpty) {
Malformatted(invalidIpConfigs)
} else {
val ipv4it: Iterable[Inet4Address] = ipConfigs.map { ipConfig =>
InetAddress.getByName(ipConfig.address).asInstanceOf[Inet4Address]
}
val dups = ipv4it.groupBy(identity).filter(_._2.size != 1).keys
if (!dups.isEmpty) {
Duplicates(dups)
} else {
val ipAvailability: Map[Inet4Address, Boolean] =
ipv4it.map(ip => (ip, isIpAvailable(ip)))
val taken: Iterable[Inet4Address] = ipAvailability.filter(!_._2).keys
if (!taken.isEmpty) {
Unavailable(taken)
} else {
Valid
}
}
}
}
I don't like the nested ifs because it makes the code less readable. Is there a nice way to linearize this code? In java, I might use return statements, but this is discouraged in scala.
I personally advocate using a match everywhere you can, as it in my opinion usually makes code very readable
def result(ipConfigs: Iterable[IpConfig]): Result =
ipConfigs.filterNot(ipc => isValidIpv4(ipc.address) && isValidIpv4(ipc.gateway)) match {
case Nil =>
val ipv4it = ipConfigs.map { ipc =>
InetAddress.getByName(ipc.address).asInstanceOf[Inet4Address]
}
ipv4it.groupBy(identity).filter(_._2.size != 1).keys match {
case Nil =>
val taken = ipv4it.map(ip => (ip, isIpAvailable(ip))).filter(!_._2).keys
if (taken.nonEmpty) Unavailable(taken) else Valid
case dups => Duplicates(dups)
}
case invalid => Malformatted(invalid)
}
Note that I've chosen to match on the else part first, since you generally go from specific to generic in matches, since Nil is a subclass of Iterable I put that as the first case, eliminating the need for an i if i.nonEmpty in the other case, since it would be a given if it didn't match Nil
Also a thing to note here, all your vals don't need the type explicitly defined, it significantly declutters the code if you write something like
val ipAvailability: Map[Inet4Address, Boolean] =
ipv4it.map(ip => (ip, isIpAvailable(ip)))
as simply
val ipAvailability = ipv4it.map(ip => (ip, isIpAvailable(ip)))
I've also taken the liberty of removing many one-off variables I didn't find remotely necessary, as all they did was add more lines to the code
A thing to note here about using match over nested ifs, is that is that it's easier to add a new case than it is to add a new else if 99% of the time, thereby making it more modular, and modularity is always a good thing.
Alternatively, as suggested by Nathaniel Ford, you can break it up into several smaller methods, in which case the above code would look like so:
def result(ipConfigs: Iterable[IpConfig]): Result =
ipConfigs.filterNot(ipc => isValidIpv4(ipc.address) && isValidIpv4(ipc.gateway)) match {
case Nil => wellFormatted(ipConfigs)
case i => Malformatted(i)
}
def wellFormatted(ipConfigs: Iterable[IpConfig]): Result = {
val ipv4it = ipConfigs.map(ipc => InetAddress.getByName(ipc.address).asInstanceOf[Inet4Address])
ipv4it.groupBy(identity).filter(_._2.size != 1).keys match {
case Nil => noDuplicates(ipv4it)
case dups => Duplicates(dups)
}
}
def noDuplicates(ipv4it: Iterable[IpConfig]): Result =
ipv4it.map(ip => (ip, isIpAvailable(ip))).filter(!_._2).keys match {
case Nil => Valid
case taken => Unavailable(taken)
}
This has the benefit of splitting it up into smaller more manageable chunks, while keeping to the FP ideal of having functions that only do one thing, but do that one thing well, rather than having god-methods that do everything.
Which style you prefer, of course is up to you.
This has some time now but I will add my 2 cents. The proper way to handle this is with Either. You can create a method like:
def checkErrors[T](errorList: Iterable[T], onError: Result) : Either[Result, Unit] = if(errorList.isEmpty) Right() else Left(onError)
so you can use for comprehension syntax
val invalidIpConfigs = getFormatErrors(ipConfigs)
val result = for {
_ <- checkErrors(invalidIpConfigs, Malformatted(invalidIpConfigs))
dups = getDuplicates(ipConfigs)
_ <- checkErrors(dups, Duplicates(dups))
taken = getAvailability(ipConfigs)
_ <- checkErrors(taken, Unavailable(taken))
} yield Valid
If you don't want to return an Either use
result.fold(l => l, r => r)
In case of the check methods uses Futures (could be the case for getAvailability, for example), you can use cats library to be able of use it in a clean way: https://typelevel.org/cats/datatypes/eithert.html
I think it's pretty readable and I wouldn't try to improve it from there, except that !isEmpty equals to nonEmpty.

Chaining validation in Scala

I have a Scala case class containing command-line configuration information:
case class Config(emailAddress: Option[String],
firstName: Option[String]
lastName: Option[String]
password: Option[String])
I am writing a validation function that checks that each of the values is a Some:
def validateConfig(config: Config): Try[Config] = {
if (config.emailAddress.isEmpty) {
Failure(new IllegalArgumentException("Email Address")
} else if (config.firstName.isEmpty) {
Failure(new IllegalArgumentException("First Name")
} else if (config.lastName.isEmpty) {
Failure(new IllegalArgumentException("Last Name")
} else if (config.password.isEmpty) {
Failure(new IllegalArgumentException("Password")
} else {
Success(config)
}
}
but if I understand monads from Haskell, it seems that I should be able to chain the validations together (pseudo syntax):
def validateConfig(config: Config): Try[Config] = {
config.emailAddress.map(Success(config)).
getOrElse(Failure(new IllegalArgumentException("Email Address")) >>
config.firstName.map(Success(config)).
getOrElse(Failure(new IllegalArgumentException("First Name")) >>
config.lastName.map(Success(config)).
getOrElse(Failure(new IllegalArgumentException("Last Name")) >>
config.password.map(Success(config)).
getOrElse(Failure(new IllegalArgumentException("Password"))
}
If any of the config.XXX expressions returns Failure, the whole thing (validateConfig) should fail, otherwise Success(config) should be returned.
Is there some way to do this with Try, or maybe some other class?
It's pretty straightforward to convert each Option to an instance of the right projection of Either:
def validateConfig(config: Config): Either[String, Config] = for {
_ <- config.emailAddress.toRight("Email Address").right
_ <- config.firstName.toRight("First Name").right
_ <- config.lastName.toRight("Last Name").right
_ <- config.password.toRight("Password").right
} yield config
Either isn't a monad in the standard library's terms, but its right projection is, and will provide the behavior you want in the case of failure.
If you'd prefer to end up with a Try, you could just convert the resulting Either:
import scala.util._
val validate: Config => Try[Config] = (validateConfig _) andThen (
_.fold(msg => Failure(new IllegalArgumentException(msg)), Success(_))
)
I wish that the standard library provided a nicer way to make this conversion, but it doesn't.
It's a case class, so why aren't you doing this with pattern matching?
def validateConfig(config: Config): Try[Config] = config match {
case Config(None, _, _, _) => Failure(new IllegalArgumentException("Email Address")
case Config(_, None, _, _) => Failure(new IllegalArgumentException("First Name")
case Config(_, _, None, _) => Failure(new IllegalArgumentException("Last Name")
case Config(_, _, _, None) => Failure(new IllegalArgumentException("Password")
case _ => Success(config)
}
In your simple example, my priority would be to forget monads and chaining, just get rid of that nasty if...else smell.
However, while a case class works perfectly well for a short list, for a large number of configuration options, this becomes tedious and the risk of error increases. In this case, I would consider something like this:
Add a method that returns a key->value map of the configuration options, using the option names as the keys.
Have the Validate method check if any value in the map is None
If no such value, return success.
If at least one value matches, return that value name with the error.
So assuming that somewhere is defined
type OptionMap = scala.collection.immutable.Map[String, Option[Any]]
and the Config class has a method like this:
def optionMap: OptionMap = ...
then I would write Config.validate like this:
def validate: Either[List[String], OptionMap] = {
val badOptions = optionMap collect { case (s, None) => s }
if (badOptions.size > 0)
Left(badOptions)
else
Right(optionMap)
}
So now Config.validate returns either a Left containing the name of all the bad options or a Right containing the full map of options and their values. Frankly, it probably doesn't matter what you put in the Right.
Now, anything that wants to validate a Config just calls Config.validate and examines the result. If it's a Left, it can throw an IllegalArgumentException containing one or more of the names of bad options. If it's a Right, it can do whatever it wanted to do, knowing the Config is valid.
So we could rewrite your validateConfig function as
def validateConfig(config: Config): Try[Config] = config.validate match {
case Left(l) => Failure(new IllegalArgumentException(l.toString))
case _ => Success(config)
}
Can you see how much more functional and OO this is getting?
No imperative chain of if...else
The Config object validates itself
The consequences of a Config object being invalid are left to the larger program.
I think a real example would be more complex yet, though. You are validating options by saying "Does it contain Option[String] or None?" but not checking the validity of the string itself. Really, I think your Config class should contain a map of options where the name maps to the value and to an anonymous function that validates the string. I could describe how to extend the above logic to work with that model, but I think I'll leave that as an exercise for you. I will give you a hint: you might want to return not just the list of failed options, but also the reason for failure in each case.
Oh, by the way... I hope none of the above implies that I think you should actually store the options and their values as an optionMap inside the object. I think it's useful to be able to retrieve them like that, but I wouldn't ever encourage such exposure of the actual internal representation ;)
Here's a solution that I came up with after some searching and scaladocs reading:
def validateConfig(config: Config): Try[Config] = {
for {
_ <- Try(config.emailAddress.
getOrElse(throw new IllegalArgumentException("Email address missing")))
_ <- Try(config.firstName.
getOrElse(throw new IllegalArgumentException("First name missing")))
_ <- Try(config.lastName.
getOrElse(throw new IllegalArgumentException("Last name missing")))
_ <- Try(config.password.
getOrElse(throw new IllegalArgumentException("Password missing")))
} yield config
}
Similar to Travis Brown's answer.

Is there a way to chain methods which return an Option-Type in a way like getOrElse does but keeps the option-type

Given snippet composes of method calls, which return an option type. I'd like to call the next method if previous call returned None. I'm able to accomplish this with this snippet
def amountToPay : Option[TextBoxExtraction] =
getMaxByFontsize(keywordAmountsWithCurrency) match {
case None => getMaxByFontsize(keywordAmounts) match {
case None => highestKeywordAmount match {
case None => getMaxByFontsize(amountsWithCurrency) match {
case None => highestAmount
case some => some
}
case some => some
}
case some => some
}
case some => some
}
but it looks quite messy. So I hope there is abetter way to do it.
Yep, orElse is a little cleaner:
def amountToPay : Option[TextBoxExtraction] =
getMaxByFontsize(keywordAmountsWithCurrency)
.orElse(getMaxByFontsize(keywordAmounts))
.orElse(highestKeywordAmount)
.orElse(getMaxByFontsize(amountsWithCurrency))
.orElse(highestAmount)
You could also just put the items in a Seq and then use something like xs.reduceLeft(_ orElse _) or xs.flatten.headOption.getOrElse(highestAmount).