"def" 和有什么不一样?和“val"定义一个函数 [英] What is the difference between "def" and "val" to define a function
问题描述
有什么区别:
def even: Int => Boolean = _ % 2 == 0
和
val even: Int => Boolean = _ % 2 == 0
两者都可以像 even(10)
一样调用.
Both can be called like even(10)
.
推荐答案
Method def even
在调用时求值并每次创建新函数(Function1
的新实例).
Method def even
evaluates on call and creates new function every time (new instance of Function1
).
def even: Int => Boolean = _ % 2 == 0
even eq even
//Boolean = false
val even: Int => Boolean = _ % 2 == 0
even eq even
//Boolean = true
使用 def
你可以在每次调用时获得新函数:
With def
you can get new function on every call:
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
- 调用时:
val
evaluates when defined, def
- when called:
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
.
Note that there is a third option: lazy val
.
它在第一次调用时进行评估:
It evaluates when called the first time:
scala> lazy val even: Int => Boolean = ???
even: Int => Boolean = <lazy>
scala> even
scala.NotImplementedError: an implementation is missing
但每次都返回相同的结果(在本例中为 FunctionN
的相同实例):
But returns the same result (in this case same instance of FunctionN
) every time:
lazy val even: Int => Boolean = _ % 2 == 0
even eq even
//Boolean = true
lazy val test: () => Int = {
val r = util.Random.nextInt
() => r
}
test()
// Int = -1068569869
test()
// Int = -1068569869 - same result
性能
val
在定义时求值.
def
对每次调用进行评估,因此对于多次调用,性能可能比 val
差.您只需一次调用即可获得相同的性能.由于没有调用,您将不会从 def
中获得任何开销,因此即使您不会在某些分支中使用它,您也可以定义它.
def
evaluates on every call, so performance could be worse than val
for multiple calls. You'll get the same performance with a single call. And with no calls you'll get no overhead from def
, so you can define it even if you will not use it in some branches.
使用 lazy val
你会得到一个惰性求值:即使你不会在某些分支中使用它,你也可以定义它,它会求值一次或从不求值,但你会得到一个对您的 lazy val
的每次访问进行双重检查锁定的开销很小.
With a lazy val
you'll get a lazy evaluation: you can define it even if you will not use it in some branches, and it evaluates once or never, but you'll get a little overhead from double check locking on every access to your lazy val
.
正如@SargeBorsch 指出的,您可以定义方法,这是最快的选择:
As @SargeBorsch noted you could define method, and this is the fastest option:
def even(i: Int): Boolean = i % 2 == 0
但是如果你需要一个函数(不是方法)用于函数组合或高阶函数(比如 filter(even)
),编译器会在你每次使用你的方法时从你的方法中生成一个函数函数,因此性能可能比 val
略差.
But if you need a function (not method) for function composition or for higher order functions (like filter(even)
) compiler will generate a function from your method every time you are using it as function, so performance could be slightly worse than with val
.
这篇关于"def" 和有什么不一样?和“val"定义一个函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!