gpt4 book ai didi

scala - 选择 def 而不是 val 的优缺点

转载 作者:行者123 更新时间:2023-12-03 02:42:56 24 4
gpt4 key购买 nike

我问的问题与 this one 略有不同。假设我有一个代码片段:

def foo(i : Int) : List[String] = {
val s = i.toString + "!" //using val
s :: Nil
}

这在功能上等同于以下内容:

def foo(i : Int) : List[String] = {
def s = i.toString + "!" //using def
s :: Nil
}

为什么我会选择其中一个而不是另一个?显然,我认为第二个在以下方面有一些缺点:

  • 创建更多字节码(内部 def 被提升为类中的方法)
  • 调用方法而不是访问值的运行时性能开销
  • 非严格评估意味着我可以轻松访问 s 两次(即不必要地重做计算)

我能想到的唯一优点是:

  • s 的非严格求值意味着仅在使用时才调用它(但随后我可以只使用 lazy val)

这里人们的想法是什么?制作所有内部 val def 对我来说是否有重大不利影响?

最佳答案

1)

我没有看到提到的一个答案是,您所描述的方法的堆栈帧实际上可能更小。您声明的每个 val 都将占用 JVM 堆栈上的一个槽,但是,每当您使用 def 获得的值时,它都会在您使用它的第一个表达式中被消耗。即使 def 引用了环境中的某些内容,编译器也会通过 .HotSpot 应该优化这两件事,至少有些人是这么说的。请参阅:

http://www.ibm.com/developerworks/library/j-jtp12214/

由于内部方法在后台编译为常规私有(private)方法,并且通常非常小,因此 JIT 编译器可能会选择内联它,然后对其进行优化。这可以节省分配较小堆栈帧的时间(?),或者通过堆栈上的元素较少,使局部变量访问速度更快。

但是,请对此持保留态度 - 我实际上还没有制定广泛的基准来支持这一说法。

2)

此外,为了扩展 Kevin 的有效回复,提供的稳定 val 还意味着您可以将其与 path dependent types 一起使用。 - 这是你不能用 def 做的事情,因为编译器不会检查它的纯度。

3)

出于另一个原因,您可能想要使用 def,请参阅不久前提出的相关问题:

Functional processing of Scala streams without OutOfMemory errors

本质上,使用 defs 生成 Streams 确保不存在对这些对象的额外引用,这对于 GC 很重要。由于 Stream 无论如何都是惰性的,因此即使您有多个 def,创建它们的开销也可能可以忽略不计。

关于scala - 选择 def 而不是 val 的优缺点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4133457/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com