Lengoman
Lengoman

Reputation: 964

How to implement "or" in a scala filter?

I am trying to implement an "or" filtering a list in scala.

    list.filter(_ % 3 ==0 || _ % 5 ==0)

but I am getting this error:

error: wrong number of parameters; expected = 1

So how can this be grouped as one parameter.

Upvotes: 2

Views: 759

Answers (4)

Victor Moroz
Victor Moroz

Reputation: 9225

Functional alternative:

val or = (xs: List[Int => Boolean]) => (x: Int) => xs.exists(_(x))

List(0, 1, 2, 3, 4, 5, 6).filter(or(List(_ % 3 == 0, _ % 5 == 0)))

or even simpler:

val or = { def or(xs: (Int => Boolean)*) = (x: Int) => xs.exists(_(x)); or _}
List(0, 1, 2, 3, 4, 5, 6).filter(or(_ % 3 == 0, _ % 5 == 0))

UPDATE: Second version doesn't seem to work with Scala 2.10, so it's better to use method:

def or[T](xs: (T => Boolean)*) = (x: T) => xs.exists(_(x))

Upvotes: 0

wheaties
wheaties

Reputation: 35970

The simplest solution is to use:

list.filter(x => (x % 3 == 0) || (x % 5 == 0))

If you want to get fancy and implement an "or", take a look at how I did it with some pimping: Predicates. The simple solution afforded pimps is:

trait Pred1[A] extends (A => Boolean){
  self =>

  def or[AA >: A](that: AA => Boolean) = new Pred1[A]{
    def apply(arg: A) = self(arg) || that(arg)
  }
}

//and somewhere in the code
implicit def f2p[A](f: A => Boolean) = new Pred1[A]{ def apply(arg: A) = f(arg) }

and so on with "and", "xor", "nxor", "nor", and "nand". Then what you do is simply come up with two functions you pass into the filter.

Note, I may be possibly replacing pimping with a type class and am playing around with some ideas in another branch but have had little free time to really dig into it.

Upvotes: 0

om-nom-nom
om-nom-nom

Reputation: 62835

Don't try to be more concise than you have to:

list.filter(x => x % 3 ==0 || x % 5 ==0)

Underscores doesn't work because n-th _ is expanded to n-th argument like this:

list.filter((x,y) => x % 3 ==0 || y % 5 ==0)

Upvotes: 10

axel22
axel22

Reputation: 32335

You can only use the placeholder syntax if the parameter appears only once in the function expression. Otherwise, you have to declare the function parameter explicitly:

list.filter(x => x % 3 == 0 || x % 5 == 0)

Multiple placeholders expand to multiple method parameters.

Upvotes: 2

Related Questions