How to use a Scala Set as a function predicate

There’s a nice Scala Set tip in the book, Functional Programming Patterns in Scala and Clojure. The tip is this:

You can use a Scala Set as a predicate to a function.

Note that a predicate is just a function that returns a Boolean value.

Examples

The author explains this with the following examples. First, create a Set named isVowel, and then show how it can be called just like a method that returns a Boolean value:

scala> val isVowel = Set('a', 'e', 'i', 'o', 'u')
isVowel: scala.collection.immutable.Set[Char] = Set(e, u, a, i, o)

scala> isVowel('a')
res0: Boolean = true

scala> isVowel('b')
res1: Boolean = false

That’s cool. It looks like isVowel is a method or function, but it’s really a Set.

Next, the author shows us how to put this feature to use. First, define a method named vowelsInString:

scala> def vowelsInString(string: String) = string.filter(isVowel).toSet
vowelsInString: (string: String)scala.collection.immutable.Set[Char]

Notice how isVowel is passed as a predicate to the filter method. That’s a nice feature.

How it works

If you’re not comfortable with how that code works, here’s a quick explanation:

  • string.filter(isVowel) returns all the vowels from the given String.
  • The toSet method reduces that list of vowels by removing all duplicates. This is a nice feature of a Set that I wrote about in the Scala Cookbook; by converting a sequence to a Set, you eliminate the duplicates.

Finally, you can see how the code works with a real String:

scala> vowelsInString("united states")
res2: scala.collection.immutable.Set[Char] = Set(u, i, e, a)

So this is a nice thing to remember:

If you want to filter a collection by testing that collection against a set of known elements, use a Set as shown in this example.

Other Scala collection methods take a predicate

Other Scala collection methods take a predicate. For instance, the count method takes a predicate:

scala> "united states".count(isVowel)
res3: Int = 5

The filterNot method also takes a predicate:

scala> "united states".filterNot(isVowel).toSet
res4: scala.collection.immutable.Set[Char] = Set(s, n, t,  , d)

See the Scaladoc for your current collection class to find many other methods that take a predicate.