Understanding Future in Scala

alberto adami

i'm writing a Play 2.3.2 application in Scala. I use the reactivemongo driver to access to a mongodb database. I've write that query the db to obtain the most used tag in the database. This method is an Action.async and is implemented as the following:

def max = Action.async { request =>

          var max: Int = 0
          var tagFound: Tag = null
          //obtain all the tags in the db.
          val futureTags: Future[List[Tag]] = Tags.all.toList
          futureTags map{ (tags: List[Tag]) => 
            tags map { (tag: Tag) => 
              //create the tag String 
              val tagName = tag.category  + ":" + tag.attr 
              //search in the db the documents where tags.tag == tag.
              val futureRequests : Future[List[recommendationsystem.models.Request]]= Requests.find(Json.obj("tags.tag" -> tagName)).toList
              futureRequests map { (requests: List[recommendationsystem.models.Request]) =>
                //get the numbers of documents matching the tag
                val number: Int= requests.size
                if(number > max) {
                  max = number
                  tagFound = tag
                }
                println(max)
              }
            }   

         val jsonObject = if(max > 0) Json.obj("tag" -> tagFound, "occurencies" -> max) else Json.obj("tag" -> "NoOne", "occurencies" -> 0)
         Ok(jsonObject)
         }


      }

But the behavior of this method is not deterministic, what's wrong?? I can't understand why the

val jsonObject = if(max > 0) Json.obj("tag" -> tagFound, "occurencies" -> max) else Json.obj("tag" -> "NoOne", "occurencies" -> 0)
             Ok(jsonObject)
             }

is execute asynchronous and don't wait that the tags map statement finished.

vitalii

I have found a few problems with your code:

  1. don't user vars, you don't know when they will be updated, hence nondeterminism. In fact don't use vars at all
  2. you use map as foreach, i.e you don't return any value from map, use foreach explicitly if you don't return any value from future
  3. to flatten Future[Future[T]] use flatMap,
  4. to transform List[Future[T]] to Future[List[T]] use Future.sequence

Here's a rewritten piece of code, I haven't compiled it, but you can get an idea of how it should work:

def max = Action.async { request =>
    Tags.all.toList.flatMap { case tags =>
      val xs = tags map { case tag =>
        val tagName = tag.category  + ":" + tag.attr 
        Requests.find(Json.obj("tags.tag" -> tagName)).toList.map (requests => (tag, requests.size) )
      }
      val f = Future.sequence(xs)
      f.map { case ys =>
         val res = ys.foldLeft(Option.empty[(Tag, Int)]) { 
            case (Some((maxTag, maxOcc)), (tag, occ)) if occ > maxOcc => Some(tag, occ)
            case (s@Some(_), _) => s
            case (None, (tag, occ)) => Some(tag, occ)
         }
         val jsonObject = res.map { case (tag, maxOcc) =>
           Json.obj("tag" -> tagFound, "occurencies" -> maxOcc)
         } getOrElse {
             Json.obj("tag" -> "NoOne", "occurencies" -> 0)
         }
         Ok(jsonObject)
      }

    }
}

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

Is Future in Scala a monad?

来自分类Dev

使用Option()的Scala Future

来自分类Dev

将Scala Future转换为Java Future

来自分类Dev

将Scala Future转换为Twitter Future

来自分类Dev

将Java Future转换为Scala Future

来自分类Dev

Scala: understanding the ::: operator

来自分类Dev

从异常中恢复,scala Future

来自分类Dev

Scala Future不能期待吗?

来自分类Dev

Scala中的Future是单子吗?

来自分类Dev

在Kotlin实施onComplete Scala Future

来自分类Dev

在Scala中修改Future [JsArray]

来自分类Dev

从 Scala Future 返回值

来自分类Dev

Scala Future不打印结果

来自分类Dev

Scala Future 多核 - 性能低下

来自分类Dev

Scala类型不匹配找到Future [A]预期Future [B]

来自分类Dev

Scala从Future [Seq [T]]提取值到Future [T]

来自分类Dev

Scala 将 Future[IOResult] 映射到 Future[Unit]

来自分类Dev

Scala-根据Future结果谓词排序

来自分类Dev

Scala将异步调用与Future同步

来自分类Dev

Scala Future奇怪的编译错误

来自分类Dev

从scala.concurrent.Future抛出异常

来自分类Dev

如何在Scala中链接Future [\ / [A,B]]?

来自分类Dev

无法在Scala中扩展Future [T]特性

来自分类Dev

Scala Future onComplete方法签名理解

来自分类Dev

使用Scala Future运行顺序过程

来自分类Dev

Scala:如何组合返回Future的方法

来自分类Dev

处理Scala中的Future [Ething]类型

来自分类Dev

在scala Future中执行类似DAG的操作

来自分类Dev

Scala Future奇怪的编译错误