从Scala中的函数返回惰性值会发生什么?

时间:2019-01-10 15:58:09

标签: scala playframework

我找到了以下代码,但不确定如何运行。这是带有Play框架的Scala代码。

    ## route file ##

    GET /:object      @controllers.ResultsController.resultController(object)
    ## ResultsController file ##

    def resultController(object: SomeObject) = {
        getResult(object)
    } 

    def private getResult(object: SomeObject): Result = {
        lazy val result = computeResult(object) match {
            case Some(response) => JsonOk(response)
            case None => JsonInternalError(...)
        }
        result
    }

我不确定何时评估result。 我的意思是,退货是在使用时必须评估的东西,还是在退货时解决?

懒惰的特性离开了函数的上下文?

在这种情况下,从不使用该值,而仅作为GET请求的结果返回。

非常感谢!

2 个答案:

答案 0 :(得分:6)

是的,懒惰的resultgetResult内部求值并返回。 Result-getResult的返回类型不是惰性的,实际上您不能将函数的返回类型定义为惰性的。如果出于某种原因您确实需要这种计算是惰性的,则可能应该像() => ResultFuture[Result]这样。

同样的想法“ 在这种情况下,从不使用该值,仅作为GET请求的结果返回。”显然是错误的。浏览器不了解Scala,它了解HTTP(一种文本格式)。这意味着框架必须将Result转换为文本形式(即序列化),并且无论如何肯定需要对其进行评估。

答案 1 :(得分:1)

我在自然的解释中添加了行号。

1  def private getResult(object: SomeObject): Result = {
2     lazy val result = computeResult(object) match {
3        case Some(response) => JsonOk(response)
4        case None => JsonInternalError(...)
5     }
6     result
7  }
  1. 它在行6上解析。因此它从方法getResult
  2. 返回实际值
  3. lazy使用synchronized锁定在里面。 lazy始终验证变量是否已解析。
  4. result变量是局部变量,始终使用且仅使用一次。因此,lazy毫无意义。

在您的示例中,根据点“ 2”和“ 3”,lazy会降低程序速度。它还可能导致行234上的潜在死锁。有关更多数据,请参见本文https://blog.codecentric.de/en/2016/02/lazy-vals-scala-look-hood/中的“方案3:与同步结合使用的死锁”。

我的建议是在此处删除lazy