问题
I have code like that:
optionBoolean.getOrElse(false) && otherOptionBoolean.getOrElse(false)
And Scalastyle tells me that it can be simplified. How?
回答1:
You can try the following:
Seq(optionBoolean, otherOptionBoolean).forall(_.contains(true))
In Scala 2.13 (it is very similar in prior versions) the forall
method is located at IterableOnce, and its implementation is:
def forall(p: A => Boolean): Boolean = {
var res = true
val it = iterator
while (res && it.hasNext) res = p(it.next())
res
}
Therefore once there is a value that doesn't satisfy the condition, the loop will break, and the rest will not be tested.
Code run at Scastie.
回答2:
This is perhaps a bit clearer:
optionBoolean.contains(true) && otherOptionBoolean.contains(true)
回答3:
Just to throw another, not-necessarily-better answer on the pile,
optionBoolean == Some(true) && otherOptionBoolean == Some(true)
or even
(optionBoolean, otherOptionBoolean) == (Some(true), Some(true))
回答4:
What about custom dsl, that let you work with Option[Boolean]
like if is was a Boolean
? With all the same operators and same behavior.
You can use something like this:
object Booleans {
def and(fb: Option[Boolean], other: => Option[Boolean]): Option[Boolean] =
fb.flatMap(b => if (!b) Some(false) else other)
def or(fb: Option[Boolean], other: => Option[Boolean]): Option[Boolean] =
fb.flatMap(b => if (b) Some(true) else other)
def negate(fb: Option[Boolean]): Option[Boolean] =
fb.map(!_)
object Implicits {
implicit class OptionBooleanDecorator(val fb: Option[Boolean]) extends AnyVal {
def &&(other: => Option[Boolean]): Option[Boolean] =
and(fb, other)
def ||(other: => Option[Boolean]): Option[Boolean] =
or(fb, other)
def unary_!(): Option[Boolean] = negate(fb)
}
}
}
and somewhere in code:
import Booleans.Implicits._
val b1 = Some(true)
val b2 = Some(true)
val b3 = b1 && b2
val b4 = b1 || b2
val b5 = !b1
You can make it work with any other container. This sort of dsl's that extend some type are quite common in Scala world.
edit:
As for last part, namely orElse
method - this could be also placed into the dsl, but in this case you loose in composability of operations. So I let all methods return an Option
.
来源:https://stackoverflow.com/questions/65123370/simplifying-optionboolean-expression-in-scala