Scala

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:

Scala forall()
Scala forall example

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:

Scala forall() - Scala exists example
Scala exists 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. The forall function is confused with this one because of similar semantics involved as for 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:

Scala forall() - Scala foreach example
Scala foreach 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:

Scala forall() - Scala forall example with Hashmap
Scala forall example with Hashmap

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.

Shubham Aggarwal

Shubham is a Java Backend and Data Analytics Engineer with more than 3 years of experience in building quality products with Spring Boot, MongoDB, Elasticsearch, MySQL, Docker, AWS, Git, PrestoDB tools and I have a deep knowledge and passion towards analytics, Micro-service based architecture, design patterns, antipatterns and software design thinking.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Inline Feedbacks
View all comments
Back to top button