scala中定义函数,FunctionName和FunctionName(_)的区别

2024-04-15

我尝试使用以下代码在 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)

into

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

然后就运行良好了。

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


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

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

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

当对象被创建时vals 立即被评估。所以编译器会回退到默认值。

2. 实施:为什么有效

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

因此,该函数将通过调用 main 方法来评估。当 on 运行程序时将调用它。

因此,添加一些打印语句(不好的风格,不要在生产代码中这样做)将帮助您在对象创建时找出 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
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

scala中定义函数,FunctionName和FunctionName(_)的区别 的相关文章

随机推荐

  • 如何重构代码以在主线程上调用 AppDelegate?

    我最近开始将我的项目从 Swift 3 Xcode 迁移到 Swift 4 Xcode 我的应用程序在运行时崩溃 因为主线程清理程序允许访问UIApplication shared delegate仅在主线程上 导致启动时崩溃 我有以下代码
  • youtube 视频作为网站背景

    有没有办法将 youtube 视频嵌入到带有 html css 和 javascript 的网页背景中 并将实际网站内容放在顶部 如何 基本上 它应该是一个自动播放 静音的视频 但访问者可以调高音量 并且该网站应该在其之上运行良好 该网站很
  • 来自直播流的语音到文本[关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我有一个 Java 应用程序 我想要转录的不是一个文件 而是一个由 Wowza 提供的实时流 rtmp
  • 如何定位除悬停在 div 上之外的同一类的所有 div?

    我有一组 div 都具有相同的类 如果可以使这更容易 它们不必具有相同的类 理想情况下 我想要的是 当用户将鼠标悬停在这些 div 之一上时 其他 div 每个都有背景图像 全部变成灰色 以将焦点放在当前悬停的 div 上 如果是悬停在上面
  • 在两个或多个窗口之间拖放 QDockWidget

    我想知道是否有人知道是否可以拖动QDockWidget http doc qt nokia com latest qdockwidget html从一个窗口到另一个窗口 我正在开发一个有很多窗口的应用程序 每个窗口都有特定的用途 我想使用
  • 使用 OpenXML 打开点文件

    我需要打开一个 DOT word 文档模板 文件 替换填充符并将其另存为文档文件 打开 DOT 文件时 我收到 文档文件已损坏 是否可以使用 OpenXML 处理 DOT 文件 UPDATE 我正在将 DOT 文件另存为 XML 手动使用
  • 如何在 emacs 中以 info 模式打开 *.info 文件?

    C x C f blah info以基础金属模式打开文件 我用过apropos并发现Info mode我认为这可能会从基本模式更改为信息模式 但这会引发 lisp 错误 如何在 emacs 中打开外部 第三方 info 文件 以便获得与查看
  • 在旋转排序数组中搜索数字

    给定一个可以旋转的排序数组 以最小的时间复杂度在其中找到一个元素 例如 数组内容可以是 8 1 2 3 4 5 假设您在其中搜索 8 该解决方案仍然适用于二分搜索 因为您需要将数组划分为要检查的两个部分 在排序数组中 您只需查看每个部分并确
  • Elm 组件和视图:什么时候应该使用 `Html msg` 以及什么时候应该使用 `Html Msg`

    我正在做一个项目 我和我的队友正在讨论哪种方法更好 在我看来Html msg似乎更通用 所以我认为我们应该尽可能使用它 但除此之外我不能给他其他理由 另外 我来自 React 和 Redux 对我来说看起来像是带有签名的组件Html Msg
  • Angular:在/src/app/app-routing.module.ts中找不到路由声明

    当我尝试为使用以下命令生成的组件添加自动路由时 ng generate module orders route orders module app module 我收到错误 Couldn t find a route declaration
  • HTML2Canvas 不渲染完整的 div,仅渲染屏幕上可见的内容

    我正在尝试使用HTML2画布 https github com niklasvh html2canvas渲染 div 的内容 这是代码 var htmlSource potenzial page 0 btn on click functio
  • Spring Cloud Stream动态通道

    我正在使用 Spring Cloud Stream 想要以编程方式创建和绑定通道 我的用例是 在应用程序启动期间 我收到要订阅的 Kafka 主题的动态列表 如何为每个主题创建一个频道 我最近遇到了类似的场景 下面是我动态创建 Subscr
  • 在 Python 中创建二维非矩形形状的三角形网格

    假设我有一组点定义二维平面中非矩形形状的周长 我需要一个函数来创建三角形网格划分 在其中可以修改三角形单元的数量并返回每个单元的 x y 坐标 谢谢 你可能应该看看 dmsh https github com nschloe dmsh py
  • 解析 JSON 帖子

    我有以下代码 data Friend Friend friend name Text friend inTwitter Bool friend twitterName Maybe Text deriveJSON drop 6 Friend
  • XQuery 中有没有办法获取自某个纪元以来的当前时间(以毫秒为单位)?

    XQuery提供各种date time功能类似于current dateTime 但是我似乎找不到一个能让我有时间的毫秒自纪元以来 提取小时 分钟和秒的函数似乎过于独立存在 获取大纪元时间 即unix时间或类似时间 的正确方法是什么XQue
  • SwiftUI:如何更改 NavigationView 的色调(背景颜色)?

    我有一个带有列表的导航视图 如何更改导航视图的颜色 还没有直接的 api要执行此操作 但您可以查看调试视图层次结构 您将看到它是一个简单的 UINavigationBar 并且所有旧解决方案也可以在这里工作 还 struct Content
  • Laravel 4 级联软删除

    是否有一种模块化方法可以在 L4 中执行级联软删除 我的数据库已经设计为通过硬删除来执行此操作 因为所有表都与另一个表相关 但是 我正在使用软删除 并且真的不想让表超载delete 我的模型中的方法 只是由于 A 模型的数量 以及 B 必须
  • 停止 Visual Studio 2013 中的“在文件中查找”搜索,该搜索将花费很长时间

    我只是在整个解决方案中搜索了某个字符串 该字符串显然存在于许多缩小的 JavaScript 文件中 这会导致 Visual Studio 进程在 查找结果 窗口中输出这些缩小文件的内容时几乎挂起 因为它们的大小高达几兆字节 一旦这个过程开始
  • 等待来自 setter 属性的异步函数

    我需要从属性设置方法等待异步函数 public String testFunc get set Await Call to the async func
  • scala中定义函数,FunctionName和FunctionName(_)的区别

    我尝试使用以下代码在 Scala 中定义递归函数 object Factorial val almostFactorial f Int gt Int gt n Int gt if n 0 1 else n f n 1 val factori