Idiomatic alternative to `if (x) Some(y) else None`
functional-programming, monads, scala
Solution
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.
Problem
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.