Unwrapping Optional Play Route Parameters In Comprehensions - scala

I have the following pattern:
Some play route with some optional parameters defined
GET /my/route controllers.something.Class.method(maybeA: Optional[Int], maybeB: Optional[Int])
In the method, I'd like to be able to use those parameters. I feel like I don't understand the proper pattern to use. What I'd like to do is something like:
blah match {
case Some(someCase) => // do something
case _ => for {
a <- maybeA
b <- maybeB
} yield {
somethingThatReturnsAFuture(a, b)
}
}
The problem is that the for comprehension returns an Option[Future[Int]], but I need it to return Future[Int]. I'd like to be able to just throw a get on the end of the comprehension, but that smells funny (and I don't actually think it's possible to just throw get at the end of the comprehension).
Any suggestions?

If something is Option then the result of the direct processing of this will be Option as well. The only way to get rid of Option is to define the None case.
val resultOpt: Option[Future[Int]] = blah match { ...
val result: Future[Int] = resultOpt match {
case Some(f) => f
case None => Future.successful(0)
}
Or just use getOrElse. The same code, different style:
val resultOpt: Option[Future[Int]] = blah match { ...
val result: Future[Int] = resultOpt.getOrElse(Future.successful(0))
A little bit more about this:
http://alvinalexander.com/scala/how-to-use-multiple-options-for-loop-comprehension

Related

Scala patternmatching: do nothing for some cases

I have to perform some actions based on cases in a pattern matching block, but only for selective cases, and nothing to be done for remaining. So is it ok to just return () for remaining cases? Something like this:
val x = ....
val y = ....
(x, y) match {
case (Some(number), Some(text)) => {
......
}
case (Some(number), None) => {
......
}
case (_, _) => () // do nothing
}
Depends what you mean by "ok". If you are asking if it will compile, you can easily answer that question yourself, by running a few snippets in a REPL and find out, that you don't even need to return a unit. Something like this works just fine:
"foo" match {
"bar" => "baz"
"bat" => 1500
_ =>
}
If however by "ok" you meant whether it is a good idea, then the answer is "probably not". As mentioned in the comments, this is not type-safe and also purely side-effecting and not referentially transparent. There is likely a better way to do what you want.
It's generally ok, if all the cases in a match result in Unit (spelled () in Scala), to have a case result in () to preserve exhaustivity.
That said, in this case, where you require the first Option to be defined to do anything, I would probably express this as:
x.foreach { number =>
y match {
case Some(text) =>
??? // note that { } aren't required in match and ??? is idiomatic for "some code here"
case None =>
???
}
}
Then again, I particularly dislike pattern matching on Option, so ymmv.

How to Check If Some Futures in a Collection Have Failed

I used traverse to execute a collection of futures like this:
val result: Future[List[Either[Error, Int]]] = Future.traverse(urls)(foo(_))
I end up with a Future[List[Either[Error, Int]]]. How can I check that one of these futures resulted in an Error?
I tried to do this but I think it is wrong because I am reading that you cannot substitute variables for futures?
val check: Future[Boolean] = result.map{
fut => fut.exists(c => c.isLeft)
}
check.map{
b => b match {
case true => // do something
case false => // do something
}
}
You can convert the result to a list of errors like this:
val errors: Future[List[Error]] = result.map(_.collect{ case Left(err) => err })
It is then possible to use Await.result to extract these error values, but that is nearly always a bad idea because it blocks the current thread.
It is better to ask "What do I want to do once the Future is complete but returns errors?". Then implement that behaviour in a map or foreach on the errors Future.

Idiomatic alternative to `if (x) Some(y) else None`

I'm finding the following pattern popping up repeatedly in my code, and my intuition says there must be some idiomatic Scala way to better express this (Monadic or otherwise):
val someCollection: Seq[Thing] = ...
val makeBlah: Seq[Thing] => Blah = ...
...
if (someCollection.nonEmpty) Some(makeBlah(someCollection)) else None
To be more specific, I'm looking for something along the lines of what you can do with Option[T]:
val someOption: Option[Thing] = ...
val makeBlah: Thing => Blah = ...
...
val result: Option[Blah] = someOption.map(makeBlah)
...but with evaluation semantics based on some predicate rather than Some/None pattern matching in map.
While the example above uses a collection--first performing a test on it, optionally followed by an operation--I don't mean to imply a collections specific use case. You could imagine a case where Boolean is lifted or coerced into some monad:
val aThing: Thing = ...
val makeBlah: Thing => Blah = ...
val thingTest: Thing => Boolean ...
// theoretical
implicit def optionOnBoolean(b: Boolean): MonadOps[Option[Boolean]] = ...
...
// NB: map could either have a Boolean parameter
// that's always true, or be Unit.
// Neither seem like good design
val result: Option[Blah] = thingTest(aThing).map(makeBlah(aThing))
Intuitively this seems like a bad idea to me because it explicitly splits the data flow since you don't really have anything to pass via map.
When looking for a general approach that has "monadic-like" behavior without a closure to capture data, one has to answer the question of what to pass to map and how its connection to the predicate. Here's the type of construct that comes to mind:
val thing: Thing = ....
val makeBlah: Thing => Blah = ...
val thingTest: (Thing) => Boolean = ...
val result: Option[Blah] = WhenOption(thing, thingTest).map(makeBlah)
My question: Does something already exist in Scala proper, or does one have to venture out to Scalaz to get this sort of construct?
Or is there some other approach that is customary/idiomatic Scala?
Edit: My question is close to Scala - "if(true) Some(1)" without having to type "else None" but I wish to address the issue of achieving it without a closure.
For completeness:
val someCollection: Seq[Thing] = ...
val makeBlah: Seq[Thing] => Blah = ...
You can use some methods on Option:
Some(someCollection).filterNot(_.isEmpty).map(makeBlah)
or as for comprehension
for(sc <- Some(someCollection) if !someCollection.isEmpty) yield makeBla(sc)
or as pattern match
someCollection match {
case Seq() => None
case x => Some(makeBlah(x))
}
But I think the if-then-else approach is the most readable one.
I would just continue doing what you're doing unless you find yourself repeating that same logic ad nauseum within the same function scope. It's readable and makes sense. That said, if you really need to, you can "lift" a PartialFunction (see here):
def foo: PartialFunction[Seq[A], B]
def fooLifted: (Seq[A] => Option[B]) = foo.lift
Now all you have to do is make your conditional logic explicit
def foo ={
case seq if predicate(seq) => doStuff(seq)
}
This is a lot more boilerplate than what you're doing.
FWIW, I do the same thing you propose:
implicit class RichBoolean(val b: Boolean) extends AnyVal {
def map[T](f: => T): Option[T] = if (b) Some(f) else None
def flatMap[T](f: => Option[T]): Option[T] = if (b) f else None
}
"map" doesn't feel right here, but I can't think of anything better. I really like this construct, it can really help keep the "flow" when doing a few consecutive operations on your data.

Scala Option - Getting rid of if (opt.isDefined) {}

My code is becoming littered with the following code pattern:
val opt = somethingReturningAnOpt
if (opt.isDefinedAt) {
val actualThingIWant = opt.get
}
Is there some way to simplify this? (it seems needlessly complex and a code smell). Ideally it would be something like:
if (Some(actualThingIWant) = somethingReturningAnOpt) {
doSomethingWith(actualThingIWant)
}
Is anything like that possible?
Maybe something like this:
somethingReturningAnOpt match {
case Some(actualThingIWant) => doSomethingWith(actualThingIWant)
case None =>
}
or as pst suggests:
somethingReturningAnOpt.foreach { actualThingIWant =>
doSomethingWith(actualThingIWant)
}
// or...
for (actualThingIWant <- somethingReturningAnOpt) {
doSomethingWith(actualThingIWant)
}
The canonical guide to Option wrangling is by Tony Morris.
Or:
somethingReturningAnOpt.map(doSomethingWith(_))
As in in:
val str = Some("foo")
str.map(_.toUpperCase)
... and use flatMap when the result of doSomethingWith is an Option itself.
val index = Option(Map("foo" -> "bar"))
index.flatMap(_.get("whatever")) // Returns None :-)
index.map(_.get("whatever")) // Returns Some(None) :-(
The following code cannot do something useful, since after the if, actualThingIWant is not always defined and as such this code will not compile, as long as you try to use actualThingIWant later.
val opt = somethingReturningAnOpt
if (opt.isDefinedAt) {
val actualThingIWant = opt.get
}
So, you have to provide a default value. This can be achieved with getOrElse:
val thingIWant = opt.getOrElse(myDefaultValue)
Or if you don't want to have actualThingIWant after the body of the if, which means you want to trigger some side-effects only if the option is defined, you can write:
opt.foreach{ thingIWant =>
println(thingIWant)
}
or a bit shorter
opt.foreach(println)

Using Either to process failures in Scala code

Option monad is a great expressive way to deal with something-or-nothing things in Scala. But what if one needs to log a message when "nothing" occurs? According to the Scala API documentation,
The Either type is often used as an
alternative to scala.Option where Left
represents failure (by convention) and
Right is akin to Some.
However, I had no luck to find best practices using Either or good real-world examples involving Either for processing failures. Finally I've come up with the following code for my own project:
def logs: Array[String] = {
def props: Option[Map[String, Any]] = configAdmin.map{ ca =>
val config = ca.getConfiguration(PID, null)
config.properties getOrElse immutable.Map.empty
}
def checkType(any: Any): Option[Array[String]] = any match {
case a: Array[String] => Some(a)
case _ => None
}
def lookup: Either[(Symbol, String), Array[String]] =
for {val properties <- props.toRight('warning -> "ConfigurationAdmin service not bound").right
val logsParam <- properties.get("logs").toRight('debug -> "'logs' not defined in the configuration").right
val array <- checkType(logsParam).toRight('warning -> "unknown type of 'logs' confguration parameter").right}
yield array
lookup.fold(failure => { failure match {
case ('warning, msg) => log(LogService.WARNING, msg)
case ('debug, msg) => log(LogService.DEBUG, msg)
case _ =>
}; new Array[String](0) }, success => success)
}
(Please note this is a snippet from a real project, so it will not compile on its own)
I'd be grateful to know how you are using Either in your code and/or better ideas on refactoring the above code.
Either is used to return one of possible two meaningful results, unlike Option which is used to return a single meaningful result or nothing.
An easy to understand example is given below (circulated on the Scala mailing list a while back):
def throwableToLeft[T](block: => T): Either[java.lang.Throwable, T] =
try {
Right(block)
} catch {
case ex => Left(ex)
}
As the function name implies, if the execution of "block" is successful, it will return "Right(<result>)". Otherwise, if a Throwable is thrown, it will return "Left(<throwable>)". Use pattern matching to process the result:
var s = "hello"
throwableToLeft { s.toUpperCase } match {
case Right(s) => println(s)
case Left(e) => e.printStackTrace
}
// prints "HELLO"
s = null
throwableToLeft { s.toUpperCase } match {
case Right(s) => println(s)
case Left(e) => e.printStackTrace
}
// prints NullPointerException stack trace
Hope that helps.
Scalaz library has something alike Either named Validation. It is more idiomatic than Either for use as "get either a valid result or a failure".
Validation also allows to accumulate errors.
Edit: "alike" Either is complettly false, because Validation is an applicative functor, and scalaz Either, named \/ (pronounced "disjonction" or "either"), is a monad.
The fact that Validation can accumalate errors is because of that nature. On the other hand, / has a "stop early" nature, stopping at the first -\/ (read it "left", or "error") it encounters. There is a perfect explanation here: http://typelevel.org/blog/2014/02/21/error-handling.html
See: http://scalaz.googlecode.com/svn/continuous/latest/browse.sxr/scalaz/example/ExampleValidation.scala.html
As requested by the comment, copy/paste of the above link (some lines removed):
// Extracting success or failure values
val s: Validation[String, Int] = 1.success
val f: Validation[String, Int] = "error".fail
// It is recommended to use fold rather than pattern matching:
val result: String = s.fold(e => "got error: " + e, s => "got success: " + s.toString)
s match {
case Success(a) => "success"
case Failure(e) => "fail"
}
// Validation is a Monad, and can be used in for comprehensions.
val k1 = for {
i <- s
j <- s
} yield i + j
k1.toOption assert_≟ Some(2)
// The first failing sub-computation fails the entire computation.
val k2 = for {
i <- f
j <- f
} yield i + j
k2.fail.toOption assert_≟ Some("error")
// Validation is also an Applicative Functor, if the type of the error side of the validation is a Semigroup.
// A number of computations are tried. If the all success, a function can combine them into a Success. If any
// of them fails, the individual errors are accumulated.
// Use the NonEmptyList semigroup to accumulate errors using the Validation Applicative Functor.
val k4 = (fNel <**> fNel){ _ + _ }
k4.fail.toOption assert_≟ some(nel1("error", "error"))
The snippet you posted seems very contrived. You use Either in a situation where:
It's not enough to just know the data isn't available.
You need to return one of two distinct types.
Turning an exception into a Left is, indeed, a common use case. Over try/catch, it has the advantage of keeping the code together, which makes sense if the exception is an expected result. The most common way of handling Either is pattern matching:
result match {
case Right(res) => ...
case Left(res) => ...
}
Another interesting way of handling Either is when it appears in a collection. When doing a map over a collection, throwing an exception might not be viable, and you may want to return some information other than "not possible". Using an Either enables you to do that without overburdening the algorithm:
val list = (
library
\\ "books"
map (book =>
if (book \ "author" isEmpty)
Left(book)
else
Right((book \ "author" toList) map (_ text))
)
)
Here we get a list of all authors in the library, plus a list of books without an author. So we can then further process it accordingly:
val authorCount = (
(Map[String,Int]() /: (list filter (_ isRight) map (_.right.get)))
((map, author) => map + (author -> (map.getOrElse(author, 0) + 1)))
toList
)
val problemBooks = list flatMap (_.left.toSeq) // thanks to Azarov for this variation
So, basic Either usage goes like that. It's not a particularly useful class, but if it were you'd have seen it before. On the other hand, it's not useless either.
Cats has a nice way to create an Either from exception-throwing code:
val either: Either[NumberFormatException, Int] =
Either.catchOnly[NumberFormatException]("abc".toInt)
// either: Either[NumberFormatException,Int] = Left(java.lang.NumberFormatException: For input string: "abc")
in https://typelevel.org/cats/datatypes/either.html#working-with-exception-y-code