Simplifying Option[Boolean] expression in Scala

微笑、不失礼 提交于 2021-01-02 07:52:28

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!