Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scala predicate composition

Tags:

scala

The java Predicate interface provides an or method that is used to combine multiple predicates. Example:

Predicate<Integer> p1;
Predicate<Integer> p2;

Predicate<Integer> p2 = p1.or(p2)

Since scala does not have the Predicate interface but uses Function1[A, Boolean] for this purpose what would be the best way to write this? Preferably without the use of external libraries.

I try to avoid the following:

val p1: (A => Boolean)
val p2: (A => Boolean)

val p3: (A => Boolean) = (a => p1(a) || p2(a))
like image 321
senjin.hajrulahovic Avatar asked Dec 06 '22 10:12

senjin.hajrulahovic


2 Answers

You could provide the Predicate functionality in an implicit value class as

implicit class Predicate[A](val p1: A => Boolean) extends AnyVal {
  def or[B >: A](p2: B => Boolean) = (a: A) => p1(a) || p2(a)
}

and then do

val gtOne = (x: Int) => x > 1
val ltMinusOne = (x: Int) => x < -1

val absGtOne = gtOne or ltMinusOne

absGtOne(-2)  // true
absGtOne(0)  // false
absGtOne(2)  // true
like image 137
joel Avatar answered Dec 23 '22 22:12

joel


You could provide an implicit conversion from A ⇒ Boolean to Predicate which supports the operations you want. Something like this:

implicit class Predicate[A](val p: A ⇒ Boolean) extends AnyVal {
  type Predicate[A] = A ⇒ Boolean

  def unary_!                     = (a: A) ⇒ !p(a)

  def ==[B >: A](x: Predicate[B]) = (a: A) ⇒ p(a) == x(a)
  def !=[B >: A](x: Predicate[B]) = (a: A) ⇒ p(a) != x(a)
  def ||[B >: A](x: Predicate[B]) = (a: A) ⇒ p(a) || x(a)
  def &&[B >: A](x: Predicate[B]) = (a: A) ⇒ p(a) && x(a)

  def  ^[B >: A](x: Predicate[B]) = (a: A) ⇒ p(a)  ^ x(a)
  def  |[B >: A](x: Predicate[B]) = (a: A) ⇒ p(a)  | x(a)
  def  &[B >: A](x: Predicate[B]) = (a: A) ⇒ p(a)  & x(a)
}

This implements all the methods available in Boolean with the same semantics, e.g. Predicate.&& will only evaluate the second predicate if the first evaluates to true, whereas Predicate.| will always evaluate both predicates.

like image 45
Jörg W Mittag Avatar answered Dec 24 '22 00:12

Jörg W Mittag