2
votes

I am trying out Scala exercise where for expression is converted to higher order function - flatMap, filter and map. I don't understand how the input to map(List(author1,author2)) is translated to book.title.

Input:

val books:List[Book] = List(
    Book(title = "kids watching", authors = List("Aavik","Arjun"))
  )

For expression:

for{
    book <- books
    name <- book.authors
    if name.startsWith("Aavik")
  } yield book.title

Higher order function:

books flatMap(book =>
    book.authors filter(name => name startsWith("Aavik")) map(_ => book.title))

Input to map is List("Aavik") and how does the map relates to book.title?

2
Your flatMap covers all. Your map is inside the flatMap, so in any point inside it, you are dealing with a single book and you can access to it through the book variableSCouto

2 Answers

1
votes

@Aavik please read How does yield work? article.

Desugared version of your example will look like:

case class Book(title: String, authors: List[String])

val books: List[Book] = List(
    Book(title = "kids watching", authors = List("Aavik","Arjun"))
  )

books.flatMap { (book: Book) => 
  book.authors.withFilter { (name: String) =>
    name.startsWith("Aavik")
  }.map { _ =>
    book.title
  }
}

As you see map { _ => book.title } has the same scope as book variable. You can run this example in Scastie.

Ammonite REPL desugar can help to investigate how does Scala translate for-comprehensions.

0
votes

if I got your question right, in the above example i.e

   for{
    book <- books
    name <- book.authors
    if name.startsWith("Aavik")
  } yield book.title

This will actually be converted to:

books.flatMap(((book) => book.authors.withFilter(((name) => name.startsWith("Aavik"))).map(((name) => book.title))))

So, as you can see we have book that is the input to the flatMap and it can be accessed anywhere inside it. So there is no issue in accessing book.title inside map as map is enclosed inside the flatMap.

Let me know if you want more clarity.