"def" 和有什么不一样?和“val"定义一个函数 [英] What is the difference between "def" and "val" to define a function

查看:22
本文介绍了"def" 和有什么不一样?和“val"定义一个函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有什么区别:

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆