Scala 函数中的值是否每次都生成?
对象和函数IsValidUID是否做了完全相同的事情,Scala 函数中的值是否每次都生成?,scala,Scala,对象和函数IsValidUID是否做了完全相同的事情, 或者对象会更快,因为函数每次都计算len和DashIndex?您可以轻松测试这一点,将睡眠添加到长度计算中 object isValidUuid { val sample = "f40473b8-9924-2a9a-bd82-7432191f2a75" val len = sample.length val dashIndices = sample.indices.filter(sample(_) == '-')
或者对象会更快,因为函数每次都计算len和DashIndex?您可以轻松测试这一点,将睡眠添加到长度计算中
object isValidUuid {
val sample = "f40473b8-9924-2a9a-bd82-7432191f2a75"
val len = sample.length
val dashIndices = sample.indices.filter(sample(_) == '-')
def apply(string: String) = {
string.length == len && dashIndices.forall(string(_) == '-')
}
}
def isValidUuid(string: String) = {
//f40473b8-9924-2a9a-bd82-7432191f2a75
val sample = "f40473b8-9924-2a9a-bd82-7432191f2a75"
val len = sample.length
val dashIndices = sample.indices.filter(sample(_) == '-')
string.length == len && dashIndices.forall(string(_) == '-')
}
是的,物体会更快,但我认为在你们的情况下,这种差异并不重要。
您最好将所有常量保留在object中(幻数/字符串总是不好的主意),而使用object进行计算并不是一个干净的解决方案。此scala代码:
object isValidUuidObj {
val sample = "f40473b8-9924-2a9a-bd82-7432191f2a75"
val len = {
Thread.sleep(1000)
sample.length
}
val dashIndices = sample.indices.filter(sample(_) == '-')
def apply(string: String) = {
string.length == len && dashIndices.forall(string(_) == '-')
}
}
def isValidUuid(string: String) = {
//f40473b8-9924-2a9a-bd82-7432191f2a75
val sample = "f40473b8-9924-2a9a-bd82-7432191f2a75"
val len = {
Thread.sleep(1000)
sample.length
}
val dashIndices = sample.indices.filter(sample(_) == '-')
string.length == len && dashIndices.forall(string(_) == '-')
}
编译到此java:
object O {
val i = 1
def foo = {
i
}
def bar = {
val x = 1
x
}
}
如您所见,函数中的所有值都被转换为局部变量,而对象中的值是类字段,它们只初始化一次(当对象初始化时)。为了清楚起见,我省略了对象初始化代码
检查我的工具,它有助于理解scala在这种情况下的工作方式。函数版本可以在编译时优化为对象版本。我更想知道的是,如果这种优化目前在scala编译器中实现,或者这种优化在某些情况下不可能实现reason@Renkai这样的优化是不可能的,,否则,scala编译器必须知道变量初始化代码的所有可能的副作用。举个简单的例子,当您有
val i=getUUID()
时,scala编译器如何知道getUUID()
是否有副作用,以及每次不调用此函数是否安全。常量可能可以优化,但我怀疑它是否实现了。不同版本的scala可能会给出结果,您使用的scalac版本是什么?@Renkai正确,但不适用于这种特殊情况。这是用ScalacV2.11.4编译的。
public class _$$anon$1$O$ {
private final int i;
public int i() {
return this.i;
}
public int foo() {
return this.i();
}
public int bar() {
final int x = 1;
return x;
}
{
this.i = 1;
}
}
// lazy object initialization omitted