1

I am having issues trying to write a method to return a Future[Map[Int,Long]].

I was in some iteration of this getting back a Future[Future[..]]. So I tried the flatMap identity.

Please see below for my code and error messages I am getting now. I am not sure what is going on here at the moment.

def aggregate(permissions: Vector[Permission]): Map[Int, Long]

def calculate(roleProfile: RoleProfile): Future[Map[Int, Long]] = {
  val roleIds = roleProfile.roles.map(r => r.id)
  db.run(permissionDao.getByRoles(roleIds.toList)).map {
    permissions =>
      aggregate(permissions)
  }
}

def generate(roleGroupId: Int): Future[Map[Int, Long]] = {
  for {
    roleGroup <- roleGroupService.getById(roleGroupId)
    roles <- roleGroupService.getRolesByGroupId(roleGroupId)
  } yield {
    calculate(RoleProfile(roleGroup.get.id, roles.toSet)) //flatMap identity
  }
}

I am getting an error message for method 'calculate':

type mismatch;
[error]  found   : scala.concurrent.Future[Map[Int,Long]]
[error]  required: Map[Int,Long]
[error]       calculate(RoleProfile(roleGroup.get.id, roles.toSet)) //flatMap identity

Now if remove the comments for 'flatMap identity' I get this error:

type mismatch;
[error]  found   : Map[Int,Long] => Map[Int,Long]
[error]  required: Map[Int,Long] => scala.concurrent.Future[?]
[error]       calculate(RoleProfile(roleGroup.get.id, roles.toSet)) flatMap identity

I'm very confused, how can I get this to return Future[Map[Int, Long]].

And more importantly, what is going on here that I just don't seem to understand. Please break things down if you can much appreciated.

Blankman
  • 259,732
  • 324
  • 769
  • 1,199
  • 2
    put the call to `calculate` into the for comprehension, like: `c <- calculate(RoleProfile...` then `yield c` – stew Dec 17 '15 at 04:33
  • Might help: http://stackoverflow.com/questions/14598990/confused-with-the-for-comprehension-to-flatmap-map-transformation/14602182#14602182 – danielnixon Dec 17 '15 at 04:42

1 Answers1

5

Since calculate, like your getById etc calls, returns a Future, you should be able to simply add it into the main part of the for-comprehension, eg:

def generate(roleGroupId: Int): Future[Map[Int, Long]] = {
  for {
    roleGroup <- roleGroupService.getById(roleGroupId)
    roles <- roleGroupService.getRolesByGroupId(roleGroupId)
    profile <- calculate(RoleProfile(roleGroup.get.id, roles.toSet))
  } yield { profile }
}
Shadowlands
  • 14,994
  • 4
  • 45
  • 43
  • 1
    @Blankman, Adding to @Shadowlands suggestion, you wrote the `flatMap` directly after `calculate` which only return a `Future[Map[...]]`. If you had put the `flatMap` to be applied on the whole for comprehension, it would have worked. I.e:`(for{...} yield{...}).flatMap(identity)` – gilad hoch Dec 17 '15 at 07:10