【问题标题】:What happens when return a lazy val from a function in Scala?从 Scala 中的函数返回惰性值时会发生什么?
【发布时间】:2019-01-10 15:58:08
【问题描述】:

我找到了以下代码,但我不确定它是如何工作的。这是带有 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。 我的意思是,return 是在使用时必须评估的东西,还是在return 时解决?

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

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

非常感谢!!!

【问题讨论】:

    标签: scala playframework


    【解决方案1】:

    是的,懒惰的resultgetResult 内部进行评估以返回。 Result - 你的getResult 的返回类型不是惰性的,实际上你不能将函数返回类型定义为惰性。如果出于某种原因你真的需要惰性计算,它可能应该类似于() => ResultFuture[Result]

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

    【讨论】:

    • 请注意,Future 并不是真的懒惰,只是异步。
    • @BrianMcCutchon,我同意,但有 2 个 cmets。 1.速度与真正的懒惰之间存在根本冲突。使用Future(有时忽略它)是该领域的可行权衡。 2.虽然我不知道这种标准实现恕我直言,Future 的实现仅在创建时捕获ExecutionContext,并且仅在某些相关方法(maponComplete、@987654334 @等)被调用不会破坏Future接口的契约。我仍然同意,如果这是您想要遵循的路线,您可能需要一些定制的东西。
    【解决方案2】:

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

    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. lazy 使用synchronized 锁定内部。 lazy 始终验证变量是否已解析。
    3. result 变量是本地变量,始终使用且仅使用一次。所以lazy 没有意义。

    在您的示例中,根据点“2”和“3”lazy 会减慢程序的速度。它还可能导致行234 上的潜在死锁。更多数据请查看本文https://blog.codecentric.de/en/2016/02/lazy-vals-scala-look-hood/中的“场景3:死锁与同步结合”。

    我的建议是在这里删除lazy

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-07-10
      • 2015-10-16
      • 1970-01-01
      • 2017-05-29
      • 1970-01-01
      相关资源
      最近更新 更多