Drafting futures with understanding

I have a Play Framework application using ReactiveMongo with MongoDB and I have the following code:

def categories(id: String): Future[Vector[Category]] = {...}
....
val categoriesFuture = categories(id)
for {
  categories: Vector[Category] <- categoriesFuture
  categoryIdsWithoutPerson: Vector[BSONObjectID] <- findCategoryIdsWithoutPerson(categories.map(_.id), personId) //Returns Future[Vector[BSONObjectID]]
  categoriesWithoutPerson: Vector[Category] <- categories.filter(category => categoryIdsWithoutPerson.contains(category.id)) //Play cites the error here
} yield categoryIdsWithoutPerson

      

To explain this code, I get Vector

of Categories

wrapped in Future

because it's like ReactiveMongo. As for

I understand it, I am using Vector

to get a list of ids from a database. Finally, I use a call filter

to store only those categories whose ids can be found in this ids list.

Everything seems pretty simple. The problem is Play is giving me the following compilation error on the last line of understanding for

:

pattern type is incompatible with expected type;
 found   : Vector[com.myapp.Category]
 required: com.myapp.Category

      

I'm not sure why the required type is a single instance Category

.

I could use some idea of ​​what I am doing wrong and / or if there is an easier or more idiomatic way of accomplishing this.

+3


source to share


1 answer


It looks like you are trying to compose Futures

with Vector

. For understanding, scala should have all the same higher types as in your case Future

. When you open up "sugar" for understanding, he just calls flatMap

everyone.

for {
  categories <- categoriesFuture
  // I'm not sure what the return type is here, but I'm guessing it a future as well
  categoryIdsWithoutPerson <- findCategoryIdsWithoutPerson(categories.map(_.id), personId)
  // Here we use = to get around need to flatMap
  categoriesWithoutPerson = categories.filter(category => categoryIdsWithoutPerson.contains(category.id))
} yield categoryIdsWithoutPerson

      



Your de-sugared code:

categoriesFuture.flatMap(categories => 
  findCategoryIdsWithoutPerson(categories.map(_.id), personId).
    flatMap(categoryIdsWithoutPerson => 
       categories.filter(category => categoryIdsWithoutPerson.contains(category.id)).
          map(_ => categoryIdsWithoutPerson))

      

+5


source







All Articles