gpt4 book ai didi

scala - 在 scala 中定义函数,FunctionName 和 FunctionName(_) 之间的区别

转载 作者:行者123 更新时间:2023-12-04 02:17:54 26 4
gpt4 key购买 nike

我尝试使用以下代码在 Scala 中定义一个递归函数:

object Factorial {
val almostFactorial = (f: Int => Int) => (n: Int) => if(n == 0) 1 else n * f(n - 1)
val factorial: Int => Int = almostFactorial(factorial)
def main(args: Array[String]) {
println(factorial(5))
}
}

以上代码编译通过但运行异常:

Exception in thread "main" java.lang.NullPointerException

但如果我改变

val factorial: Int => Int = almostFactorial(factorial)

进入

val factorial: Int => Int = almostFactorial(factorial(_))

然后它运行良好。

这两个声明之间有什么区别,为什么第一个声明会导致该异常?

最佳答案

1。实现:为什么这会导致空指针异常

val factorial: Int => Int = {
println(s"Before recursive def: $factorial")
almostFactorial(factorial)
}

运行此代码会向您显示在递归定义中 factorialnull。答案在于将 Scala 函数值作为 JVM 中的对象来实现。由于对象的默认值为 null 并且阶乘在分配给 val factorial : Int => Int 时尚未初始化为 null

随着对象的创建,val 会立即被评估。所以编译器回退到默认值。

2。实现:为什么这行得通

通过使用 fun _ 语法,您可以将函数的实现更改为 部分应用函数。当您提供 Int 时,将对其进行评估。因此它不会在评估 val 的同时进行评估。

所以这个函数将通过调用 main 方法来评估。在运行程序时将调用它。

因此添加一些打印语句(糟糕的风格,不要在生产代码中这样做)将帮助您在对象创建时找出 vals 的值:

  val factorial: Int => Int = {
println(s"Before recursive def: $factorial")
val partialFactorial = factorial(_)
println(partialFactorial)
almostFactorial(partialFactorial)
}

运行第二个实现你会得到这个输出

Before recursive def: null
<function1> <- Partial applied factorial(_)
120

扩展示例:为什么使用部分应用函数不会在此处自动保护您

因此该函数在对象创建时为null。如果您在 val 的实现中直接将值提供给部分应用函数,如本例所示:

  val factorial: Int => Int = {
println(s"Before recursive def: $factorial")
val partialFactorial = factorial(_)
println(partialFactorial)
println(partialFactorial(2)) // here we will again cause a null pointer exception
almostFactorial(partialFactorial)
}

您再次遇到空指针异常:

$scala Factorial

Before recursive def: null
<function1>
java.lang.NullPointerException
at Factorial$$anonfun$1.apply$mcII$sp(Example.scala:5)s

关于scala - 在 scala 中定义函数,FunctionName 和 FunctionName(_) 之间的区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32910021/

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