Scala make multiple option checks more concise

2019-05-05 18:30发布

Working with Options in Scala and Play Framework, is there a more concise way of checking x amount of variables like so?

if (a.isDefined || b.isDefined || c.isDefined || d.isDefined ...) {

}

Is a one liner something like (a,b,c,d).isDefined possible?

Thanks

3条回答
闹够了就滚
2楼-- · 2019-05-05 18:45

On top of my head, probably there's a nicer way:

List(a, b, c, d).exists(_.isDefined)

For ands (from Rob Starling comment):

List(a, b, c, d).forall(_.isDefined)

You could also have more complex condition compositions:

// (a || b) && (c || d)
List(
  List(a, b).exists(_.isDefined), 
  List(c, d).exists(_.isDefined)
).forall(identity)

// (a && b) || (c && d)
List(
  List(a, b).forall(_.isDefined), 
  List(c, d).forall(_.isDefined)
).exists(identity)

And so on.

查看更多
Viruses.
3楼-- · 2019-05-05 18:56

Considering that you seem to be within the playframework and that you probably not only want to check whether the / or a value is defined but also use them, you could use the following code using the type classes of the play framework without using scalaz.

import play.api.libs.functional._
import play.api.libs.functional.syntax._
implicit def optionInstance[A] = new Applicative[Option] with Alternative[Option] {
  override def pure[A](a: A): Option[A] = Option(a)

  override def apply[A, B](mf: Option[(A) => B], ma: Option[A]): Option[B] = for {
    f <- mf
    a <- ma
  } yield f(a)

  override def map[A, B](m: Option[A], f: (A) => B): Option[B] = m map f

  override def app: Applicative[Option] = this 

  override def `|`[A, B >: A](alt1: Option[A], alt2: Option[B]): Option[B] = {
    (alt1, alt2) match {
      case (Some(_), None) => alt1
      case (None, Some(_)) => alt2
      case _ => None
    }
  }
  override def empty: Option[Nothing] = None
}

// examples

val optI = Option(3)
val optS = Option("Hello")
val optNone : Option[String] = None

(optI and optS ) {(i, s) => s"$i $s"}
(optI and optS and (optNone or Option("world")) ) { (i,s,w) => s"$i $s $w"}
查看更多
地球回转人心会变
4楼-- · 2019-05-05 19:02

On an aesthetic basis:

scala> val a,b = Some(7)
a: Some[Int] = Some(7)
b: Some[Int] = Some(7)

scala> val c,d: Option[Int] = None
c: Option[Int] = None
d: Option[Int] = None

scala> a orElse b isDefined
res0: Boolean = true

scala> c orElse d isDefined
res1: Boolean = false

scala> a orElse c isDefined
res2: Boolean = true

I could do that all day.

scala> c orElse d orElse a orElse b isDefined
res3: Boolean = true

Yup, just checking that I could do it all day.

查看更多
登录 后发表回答