Scala forall() Example
1. Introduction
In this lesson, we will look at some excellent examples of Scala’s forall()
function and how it can be used various scenarios to apply predicate logic over a collection of elements. It is one of the simplest functions to use in Scala and apply a simple logic in terms of functional programming as it allows us to define an inline predicate for which we do not have keep a function separately if it needs to be used just once. Well, we never know this so this can be a disadvantage as well. Due to this, we can just pass an evaluator function to the forall function which will be evaluated for the elements this function is iterating over.
Let’s start our lesson to look at what anatomy does Scala’s forall()
function has. To run the program, we are using an online compiler known as Scastie which is an excellent tool to run Scala programs without having to go through the process of installing and running Scala on your local machine.
2. Scala’s forall() function
In this section, we will look at various ways to apply predicate logic over a collection of elements, which can be anything, a List, a Set or a Map. We will also look at how more operations can be coupled with the function to increase its capabilities and perform multiple operations in a single go.
2.1 Iterating over a Collection
Let’s start with a simple example of how to apply predicate logic over a collection of elements in Scala.
The forall
method takes a function func
that returns a Boolean. The semantics of forall
says: return true
if for every x in the collection, p(x) is true. Here is a programmatic example for the same:
Scala forall example
List(1,2,3,4,5).forall(x => x < 3)
means: true if 1, 2, 3, 4, 5 are less than 3, false otherwise. In this case, it will evaluate to false since it is not the case all elements are less than 3: 3, 4 and 5 are not less than 3. Here is the output for the example when we run the example above with Scastie tool:
There is a similar method exists
that returns true if there is at least one element x in the collection such that p(x) is true. Here is a programmatic example for the same:
Scala exists example
List(1,2,3,4,5).exists(x => x < 3)
means: true if at least one of 1, 2, 3, 4, 5 is less than 3, false otherwise. In this case, it will evaluate to true since it is the case some element is less than 3: e.g. 1 is less than 3. Here is the output for the example:
2.2 Forall vs Foreach function
One of the confusing elements in Scala (at leats for the beginners) is the difference between the Forall
vs Foreach
function. Here are the two key points about the functions:
- The
forall
function accepts a boolean predicate which when evaluated, the function will return if it has evaluated true for all of the elements in the collection or not. - The
Foreach
function allows us to iterate over a collection of elements. Theforall
function is confused with this one because of similar semantics involved asfor
keyword.
Let us look at a simple example on how we can make use of the Foreach
function to iterate over the elements:
Scala Foreach example
List(1,2,3,4,5).foreach(print(_))
Here is the output for the example:
2.3 Forall function with empty collection
One of the most confusing situation arises when we need to check or evaluate a condition against a collection of items. But can you guess what happens if those collections of items are actually empty? Well, let’s look at the source code of the forall function before we make a comment on this scenario:
Scala Forall source code
def forall(p: A => Boolean): Boolean = { var these = this while (!these.isEmpty) { ... } true }
This clearly means that if the collection of items over which the forall function is applying the predicate logic is empty, it will return true. We can rephrase that forall
means that none of the elements of the list violate the given predicate. In case there are no elements, none of them violates it.
The semantics of these methods was chosen to be coherent with the semantics of the universal and the existential quantifier in formal logic. Method forall
acts as the universal quantifier – it returns true
if there is no element in the collection for which the predicate is false. If there are no elements, then the predicate is never false and forall
is true. This is opposed to the exists
function we looked at earlier. Method exists
acts as the existential quantifier. It returns true if there is at least one element for which the predicate is true. If there are no elements, then the predicate is never true and exists returns false.
2.4 Forall function with Hashmap
There is a different way in which we can use the forall()
function with HashMaps in Scala. Suppose you want to apply a condition on the keys of the HashMap you have to check if all the key-value pairs pass a validation test. Here is a way of testing the same with the following code snippet:
Scala Forall with HashMap
import scala.collection.mutable object MapFor { def main(args: Array[String]): Unit = { val myMap = mutable.HashMap[Int, Int](1 -> 10, 2 -> 20) val areAllValuesTenTimesTheKey = myMap.forall { case (k, v) => k * 10 == v } println(areAllValuesTenTimesTheKey) } }
Here is the output for the example:
The problem is that forall wants a function that takes a single Tuple2
, rather than two arguments. (We’re thinking of a Map[A,B]
as an Iterable[(A,B)]
when we use forall
.) Using a case statement is a nice workaround; it’s really using pattern matching here to break apart the Tuple2
and give the parts names. If you don’t want to use pattern matching, you could have also written:
Scala Forall with HashMap
val areAllValuesTenTimesTheKey = myMap.forall(p => p._1 * 10 == p._2 }
But I think that is much less visualisable and difficult to understand.
2.5 Mixing getOrElse with forall
In Scala, we can define an option as:
Option in Scala
val names : Option[Seq[String]] = Option(Seq("John", "Tyrion", "Bob")) names.get.forall(m => Seq("Bob").contains(m))
This will create a false outout but we can replace this with a getOrElse
to avoid NPE. For this, we can first map
the sequence inside Option
to a boolean value, and then getOrElse
the final result, providing a default boolean value, like:
Mixing Forall with getOrElse
names.map(_.forall(m => Seq("Bob").contains(m))).getOrElse(false)
To add, the inner lambda can also be abbreviated like:
Mixing Forall with getOrElse
names.map(_.forall(Seq("Bob").contains)).getOrElse(false)
3. Conclusion
In this lesson, we looked at some excellent examples of Scala’s forall()
function and how it can be used in various scenarios to apply predicate logic over a collection of elements. We also looked at the internal implementation of the forall
function and looked at how it behaves when an empty collection is applied over it and most importantly, we understood the formal logic behind its implementation.
Well, the biggest challenge for any programmer, may he be comfortable with Java, Kotlin, Python or any other programming language is to learn another programming language. This is because when we are comfortable with a programming language, we tend to find the same qualities in the new programming language as well which, in most cases, presents disappointment because there is always something new in each programming language. If you are a Java Developer and looking for a Scala tutorial, head over to the Scala Tutorial for Java Developers for a practical lesson about how you can get started with Scala.