Skip to content
Search

Scala:ForComprehensions

lastmod 2020-09-11created 2020-08-275 edits

About

The Scala Doc says the following.

Like the yield in Python, Ruby, etc., Scala also has yield, but it is a bit different. Scala's yield is used as part of for comprehensions, which are a generalization of list comprehensions in other languages. Scala's "for comprehensions" are equivalent to Haskell's "do" and are nothing more than syntactic sugar for multiple monadic operations.

Examples

Just a simple for loop:

for(i <- 1 to 3) {
  println(i)
}

Just a simple for loop:

val a =  for(i <- 1 to 3) yield i;
println(a) // Vector(1, 2, 3)

Add a multiplication to the yield value.

val a =  for(i <- 1 to 3) yield i * 100;
println(a) // Vector(100, 200, 300)

Add a condition. (The result is applied as Boolean)

val a =  for(i <- 1 to 3) yield i > 2;
println(a) // Vector(false, false, true)

Put an if statement in the for condition before yield. It has the effect of a filter.

val a = for( i <- 1 to 3 ; if i == 1 ) yield i
println(a) // Vector(1)

Using multiple if statements applies multiple filters:

val a = for( i <- 1 to 10 ; if i > 5 ; if i % 2 == 0 ) yield i
println(a) // Vector(6, 8, 10)

You can use a List, and expand it using { }:

val list = List(1, 2, 3)
val a = for {
  element <- list
} yield {
  element
}
println(a) // List(1, 2, 3)

Expand the yield body using { }:

val list = List(1, 2, 3)
val a = for {
  i <- list
} yield {
  i > 2
}
println(a) // List(false, false, true)

Filtering with if is also possible:

val list = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
val a = for {
  i <- list
  if i > 5
  if i % 2 == 0
} yield {
  i
}
println(a) // List(6, 8, 10)

Using multiple Lists in a for loop:

val list = List(1, 2, 3)
val list2 = List(10, 20)
val a = for {
  i <- list
  j <- list2
} yield {
  i
}
println(a) // List(1, 1, 2, 2, 3, 3)

Operations with two lists are possible:

val list = List(1, 2, 3)
val list2 = List(10, 20)
val a = for {
  i <- list
  j <- list2
} yield {
  i * j
}
println(a) // List(10, 20, 20, 40, 30, 60)

Using three lists:

val list = List(1, 2, 3)
val list2 = List(10, 20)
val list3 = List(1, 2)
val a = for {
  i <- list
  j <- list2
  z <- list3
} yield {
  i + j + z
}
println(a) // List(12, 13, 22, 23, 13, 14, 23, 24, 14, 15, 24, 25)

You can also make tuples.

val list = List(1, 2, 3)
val list2 = List("x", "y")
val a = for {
  i <- list
  j <- list2
} yield {
  (i, j)
}
println(a) // List((1,x), (1,y), (2,x), (2,y), (3,x), (3,y))

You can use the zip function, which combines the elements of two lists into one, to make a single list, and then use for.. yield.

val names = List("Jax", "Peter", "Tony")
val scores = List(100, 80, 90)
val zipped = names.zip(scores)
val example = for ((name, score) <- zipped) yield name + "-" + score
println(example) // List(Jax-100, Peter-80, Tony-90)

It can also be used to find common elements of two lists.

val list1 = List(1, 2, 3)
val list2 = List(7, 9, 1)
val result = for (e1 <- list1 ; e2 <- list2 if e1 == e2) yield e1
print(result) // List(1)

No yield example

Can be used without yield:

for (i <- Iterator.range(0, 20);
    j <- Iterator.range(i + 1, 20) if i + j == 32)
  println("(" + i + ", " + j + ")")

It is similar to an ordinary loop in imperative languages. The result is:

(13, 19)
(14, 18)
(15, 17)

See also

Favorite site

author Zer0 sitemap