Scala “与”的区别是什么;def";及;val";定义函数
以下两者之间的区别是什么:Scala “与”的区别是什么;def";及;val";定义函数,scala,Scala,以下两者之间的区别是什么: def even: Int => Boolean = _ % 2 == 0 及 两者都可以称为偶数(10)考虑一下: scala> def even: (Int => Boolean) = { println("def"); (x => x % 2 == 0) } even: Int => Boolean scala> val even2: (Int =>
def even: Int => Boolean = _ % 2 == 0
及
两者都可以称为偶数(10)考虑一下:
scala> def even: (Int => Boolean) = {
println("def");
(x => x % 2 == 0)
}
even: Int => Boolean
scala> val even2: (Int => Boolean) = {
println("val");
(x => x % 2 == 0)
}
val //gets printed while declaration. line-4
even2: Int => Boolean = <function1>
scala> even(1)
def
res9: Boolean = false
scala> even2(1)
res10: Boolean = false
初始化x
时,Random.nextInt
返回的值被设置为x
的最终值。下次再次使用x
时,它将始终返回相同的值
您还可以延迟初始化x
。i、 e.第一次使用时,它是初始化的,而不是在声明时。例如:
scala> lazy val y = { Random.nextInt }
y: Int = <lazy>
scala> y
res4: Int = 323930673
scala> y
res5: Int = 323930673
scala>lazy val y={Random.nextInt}
y:Int=
scala>y
res4:Int=323930673
scala>y
res5:Int=323930673
考虑一下:
scala> def even: (Int => Boolean) = {
println("def");
(x => x % 2 == 0)
}
even: Int => Boolean
scala> val even2: (Int => Boolean) = {
println("val");
(x => x % 2 == 0)
}
val //gets printed while declaration. line-4
even2: Int => Boolean = <function1>
scala> even(1)
def
res9: Boolean = false
scala> even2(1)
res10: Boolean = false
初始化x
时,Random.nextInt
返回的值被设置为x
的最终值。下次再次使用x
时,它将始终返回相同的值
您还可以延迟初始化x
。i、 e.第一次使用时,它是初始化的,而不是在声明时。例如:
scala> lazy val y = { Random.nextInt }
y: Int = <lazy>
scala> y
res4: Int = 323930673
scala> y
res5: Int = 323930673
scala>lazy val y={Random.nextInt}
y:Int=
scala>y
res4:Int=323930673
scala>y
res5:Int=323930673
方法def-even
在调用时求值,并每次创建新函数(函数1的新实例)
使用def
可以在每次调用时获得新函数:
val test: () => Int = {
val r = util.Random.nextInt
() => r
}
test()
// Int = -1049057402
test()
// Int = -1049057402 - same result
def test: () => Int = {
val r = util.Random.nextInt
() => r
}
test()
// Int = -240885810
test()
// Int = -1002157461 - new result
val
在定义时求值,def
-调用时:
scala> val even: Int => Boolean = ???
scala.NotImplementedError: an implementation is missing
scala> def even: Int => Boolean = ???
even: Int => Boolean
scala> even
scala.NotImplementedError: an implementation is missing
请注意,还有第三个选项:lazy val
它在第一次调用时求值:
scala> lazy val even: Int => Boolean = ???
even: Int => Boolean = <lazy>
scala> even
scala.NotImplementedError: an implementation is missing
性能
val
在定义时进行计算
def
在每次调用时进行评估,因此对于多个调用,性能可能比val
差。您只需拨打一个电话即可获得相同的性能。如果没有调用,您将不会从def
中获得任何开销,因此您可以定义它,即使您不会在某些分支中使用它
使用lazy val
您将得到一个懒惰的计算:即使您不在某些分支中使用它,您也可以定义它,并且它会计算一次或从未计算过,但是对lazy val
的每次访问进行双重检查锁定会带来一些开销
正如@SargeBorsch所指出的,您可以定义方法,这是最快的选项:
def even(i: Int): Boolean = i % 2 == 0
但如果您需要一个函数(而不是方法)用于函数合成或更高阶函数(如
filter(even)
),编译器将在您每次将其用作函数时从您的方法生成一个函数,因此,性能可能比使用val
方法def时稍差,甚至每次调用时都会求值并创建新函数(新的Function1
)
使用def
可以在每次调用时获得新函数:
val test: () => Int = {
val r = util.Random.nextInt
() => r
}
test()
// Int = -1049057402
test()
// Int = -1049057402 - same result
def test: () => Int = {
val r = util.Random.nextInt
() => r
}
test()
// Int = -240885810
test()
// Int = -1002157461 - new result
val
在定义时求值,def
-调用时:
scala> val even: Int => Boolean = ???
scala.NotImplementedError: an implementation is missing
scala> def even: Int => Boolean = ???
even: Int => Boolean
scala> even
scala.NotImplementedError: an implementation is missing
请注意,还有第三个选项:lazy val
它在第一次调用时求值:
scala> lazy val even: Int => Boolean = ???
even: Int => Boolean = <lazy>
scala> even
scala.NotImplementedError: an implementation is missing
性能
val
在定义时进行计算
def
在每次调用时进行评估,因此对于多个调用,性能可能比val
差。您只需拨打一个电话即可获得相同的性能。如果没有调用,您将不会从def
中获得任何开销,因此您可以定义它,即使您不会在某些分支中使用它
使用lazy val
您将得到一个懒惰的计算:即使您不在某些分支中使用它,您也可以定义它,并且它会计算一次或从未计算过,但是对lazy val
的每次访问进行双重检查锁定会带来一些开销
正如@SargeBorsch所指出的,您可以定义方法,这是最快的选项:
def even(i: Int): Boolean = i % 2 == 0
但是,如果您需要一个函数(而不是方法)用于函数合成或更高阶函数(如过滤器(偶数)
),编译器将在您每次将其用作函数时从您的方法生成一个函数,因此性能可能比val
稍差。请参见以下内容:
var x = 2 // using var as I need to change it to 3 later
val sq = x*x // evaluates right now
x = 3 // no effect! sq is already evaluated
println(sq)
令人惊讶的是,这将打印4而不是9!val(偶数var)立即计算并分配。
现在将val更改为def。。它将打印9!Def是一个函数调用。。它将在每次调用时进行评估。请参见以下内容:
var x = 2 // using var as I need to change it to 3 later
val sq = x*x // evaluates right now
x = 3 // no effect! sq is already evaluated
println(sq)
令人惊讶的是,这将打印4而不是9!val(偶数var)立即计算并分配。
现在将val更改为def。。它将打印9!Def是一个函数调用。。它将在每次调用时进行求值。此外,Val是按值求值。这意味着在定义过程中计算右侧表达式。其中Def是按名称计算的。在使用之前,它不会求值。此外,Val是按值求值。这意味着在定义过程中计算右侧表达式。其中Def是按名称计算的。在使用之前,它不会进行计算。val,即“sq”是由Scala定义的,是固定的。它是在声明时计算的,以后不能更改。在其他示例中,even2也是val,但它是用函数签名声明的,即“(Int=>Boolean)”,因此它不是Int类型。它是一个函数,其值由以下表达式设置
{
println("val");
(x => x % 2 == 0)
}
根据Scala val属性,您不能将另一个函数分配给even2,规则与sq相同
关于为什么调用eval2 val函数不反复打印“val”
原始代码:
val even2: (Int => Boolean) = {
println("val");
(x => x % 2 == 0)
}
我们知道,在Scala中,上述类型表达式的最后一条语句(在{..}内)实际上是返回到左侧。因此,您最终将even2设置为“x=>x%2==0”函数,该函数与您为even2 val类型声明的类型相匹配,即(Int=>Boolean),因此编译器很高兴。现在even2只指向“(x=>x%2==0)”函数(而不是之前的任何其他语句,如println(“val”)等。使用不同参数调用event2实际上将调用“(x=>x%2==0)”代码,因为只有该代码与event2一起保存
scala> even2(2)
res7: Boolean = true
scala> even2(3)
res8: Boolean = false
为了进一步澄清这一点,下面是c语言的不同版本
scala> def even: Int => Boolean = { _% 2 == 0 }
even: Int => Boolean
scala> val even: Int => Boolean = { _% 2 == 0 }
even: Int => Boolean = $$Lambda$1157/1017502292@57a0aeb8