Open In App

Scala For Comprehensions

Improve
Improve
Like Article
Like
Save
Share
Report

Comprehensions have the structure for (enumerators) yield e, wherever enumerators refers to a semicolon-separated list of enumerators. Enumerator is either a generator that introduces new variables, or it’s a filter. A comprehension evaluates the body e for every binding generated by the enumerators and returns a sequence of those values.

These definitions lead us to the for comprehension ideas of generators, filters, and definitions. A Scala for comprehension will contain the subsequent 3 expressions:

  • Generators
  • Filters
  • Definitions

Syntax:

for {
    b <- books             // generator
    n = b.name               // definition
    if (n startsWith "To")   // filter
} yield

 
Generators -
Generators have below form:

pattern <- expression

For example b <- books In this expression the value b iterates over all of the elements contained in books.
Below are two more things about generators -

  • Each for comprehension begins with a generator.
  • for comprehensions will be multiple generators.

Definitions -

For comprehension definitions have below syntax:

pattern = expression

For example n = b.name the variable n is bound to the value b.name. That statement has a similar result as writing this code outside of a for comprehension. val n = b.name

Filters -

For comprehension filters have below form:

if (expression)

Expression have the type Boolean. Filters drop all elements from the iteration that which expression returns false, as like given code. For example if (n startsWith "Ca") any value n that does not start with the string Ca will be dropped during the iteration process.

Let's discuss some examples.

Example #1: With yield




// Scala program of for comprehensions
  
// Creating object 
object Geeks 
  
    // Main method 
    def main(args: Array[String]) 
    
        // Creating case class    
        case class Language(name: String, article: Int)
          
        val LanguageBase = List(Language("Scala", 26),
                                Language("Csharp", 32),
                                Language("Perl", 42),
                                Language("Java", 22))
          
        // Applying for comprehensions
        // Generator
        // Definition
        val MoreThanTwenty = for (language <- LanguageBase
        if (language.article >=20 && language.article < 30))// Filters
          
         // i.e. add this to a list
          yield language.name 
          
        // Print more than twenty 
        MoreThanTwenty.foreach(name => println(name))
      
    


Output :

Scala
Java

In above example, the for loop used with a yield statement actually creates a List. Because we said yield language.name, it’s a List[String]. language <- LanguageBase is our generator and if (language.article >=20 && language.article < 30) could be a guard that filters out article those don't seem to be in between 20 to 30.
 
Example #2: Without yield

We can omit yield in comprehension. In that case, comprehension will return Unit. This can be helpful just in case we would like to perform side-effects. Here’s a program like the above one, without using yield.




// Scala program to print Hello, Geeks! 
// by using object-oriented approach 
  
// creating object 
object Geeks { 
  
// Main method 
def main(args: Array[String]) 
      
def check(a: Int) =
   for (i <- 0 until 4;
        j <- 0 until 4 if i * j >= a)
   println(s"($i, $j)")
  
check(4)


Output:

(2, 2)
(2, 3)
(3, 2)
(3, 3)

In above example, a = 4. In the first iteration, i = 0 and j = 0 so i * j is not greater than equal to a and therefore nothing is yielded. j gets incremented 3 more times before i gets incremented to 1.


Last Updated : 19 May, 2019
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads