为什么部分应用函数会延迟 Scala 中的类实例化?

2024-04-05

想象一下这段代码:

class Foo {
  println("in Foo")

  def foo(a: Int) = a + 1
}

现在,如果我们调用:

new Foo().foo _

将按预期创建 Foo 类的实例:

in Foo
res0: (Int) => Int = <function1>

但是,如果我们调用这个:

new Foo().foo(_)

Foo 的构造函数不会被调用:

res1: (Int) => Int = <function1>

如果我们接着说:

res1(7)

那是 Foo 被实例化的时候:

in Foo
res2: Int = 8

为什么 Eta 展开与偏函数应用在类实例化方面会产生差异?


天哪,这是一个微妙的问题,但据我所知,它遵循Scala 规范 http://www.scala-lang.org/docu/files/ScalaReference.pdf完全地。我将引用 2.9 版规范中的内容。

对于您的第一个示例:正如您所说,您正在通过方法值的特殊情况(第 6.7 节)看到 eta 扩展:

The expression e _ is well-formed if e is of method type or if e is a call-by-name parameter. If e is a method with parameters, e _ represents e converted to a function type by eta expansion.

§6.26.5 中给出了 eta 扩展的算法,您可以按照该算法对表达式进行以下替换new Foo().x1 _:

{
  val x1 = new Foo();
  (y1: Int) => x1.(y1);
}

这意味着当使用 eta 扩展时,所有子表达式都会在转换发生时进行计算(如果我正确理解了短语“最大子表达式”的含义),并且最终表达式是创建的的匿名函数。

在第二个示例中,这些额外的括号意味着编译器将查看第 6.23 节(特别是“匿名函数的占位符语法”)并直接创建匿名函数。

An expression (of syntactic category Expr) may contain embedded underscore symbols _ at places where identifiers are legal. Such an expression represents an anonymous function where subsequent occurrences of underscores denote successive parameters.

在这种情况下,按照该部分中的算法,您的表达式最终将是这样的:

(x1: Int) => new Foo().foo(x1)

差异是微妙的,正如 @Antoras 很好地解释的那样,只有在存在副作用代码时才真正显示出来。

请注意,针对涉及按名称调用代码块的情况正在修复错误(例如,请参阅这个问题 https://stackoverflow.com/q/4918362/991432, this bug https://issues.scala-lang.org/browse/SI-302 and this bug https://issues.scala-lang.org/browse/SI-5610).

后记:在这两种情况下,匿名函数(x1:Int) => toto扩展到

new scala.Function1[Int, Int] {
  def apply(x1: Int): Int = toto
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么部分应用函数会延迟 Scala 中的类实例化? 的相关文章

随机推荐

  • Facebook Graph API 不返回事件图片

    编辑 看来 Facebook 终于修复了这个错误 你能帮我理解为什么会发生这种情况吗 这是一个公开活动 附有图片 https www facebook com events 282054218538223 https www faceboo
  • 如何在窗口模式下禁用 VS Code 小地图?

    我在 Visual Studio Code 中执行了以下操作 settings json gt editor minimap enabled true 并排打开 2ed 文件 窗口模式 小地图存在于两个窗口中 这占用了太多空间 但当我在单个
  • 如何实现pdf编辑器

    I am working on an application and I am using pdfkit which I should have the ability to read pdf files and edit them I f
  • 如何在 ElasticSearch 中从形状获取交点

    我已经存储了一条路线ElasticSearch作为多边形 现在我有一个圆 一个点和一个半径 我可以检查圆点是否与多边形相交 下面是我使用的代码 问题 如何获取与圆相交的路线上的点 public Boolean isMatchingDoc L
  • 省略 Doctrine 生成的 SQL 的鉴别器部分

    假设以下情况AbstractPage model ORM Entity ORM Table name page ORM InheritanceType SINGLE TABLE ORM DiscriminatorColumn name ty
  • 在单个查询中从 mongo 中删除多个文档

    我有一个要删除的 mongo id 列表 目前我正在这样做 inactive users gt list of inactive users for item in inactive users db users remove id ite
  • VHDL (Xilinx) 中的错误:无法链接设计

    为什么我在 VHDL 中遇到错误 另外 有时 无法执行流程 因为之前的流程失败了 非常感谢 永久解决方案1 在win 10上 找出 installation directory Xilinx 14 x ISE DS ISE gnu MinG
  • 为什么会有 CL_DEVICE_MAX_WORK_GROUP_SIZE?

    我试图了解 OpenCL 设备 例如 GPU 的体系结构 但我不明白为什么本地工作组中的工作项数量有明确的限制 即常量 CL DEVICE MAX WORK GROUP SIZE 在我看来 这应该由编译器处理 即 如果 为简单起见 一维 内
  • 云平台- sudo:无法解析主机[关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我在 Amazon EC2 和 openstack 上使用 Linux 作为基于云的服务器 当尝试运行时 sudo chhown ubun
  • 什么时候应该在汇编中使用显式对齐指令?

    我花了一些时间进行汇编编程 特别是 Gas 最近我了解了对齐指令 我想我已经了解了最基本的知识 但我想更深入地了解其本质以及何时使用对齐 例如 我想知道一个简单的 C switch 语句的汇编代码 我知道在某些情况下switch语句是基于跳
  • 如何使用 Node.js 中的 WebSocket (websockets/ws) 库获取客户端 IP 地址?

    我在客户端对象上找不到客户端 IP 参数 经过一番尝试找出客户端 网络浏览器 IP 地址是哪一个提供的 答案是 ws socket remoteAddress 或者如果您有权访问req via wss on connection ws re
  • 无法登录 Openshift

    我已经尝试通过 Openshift 连接到我的应用程序好几天了 但仍然没有成功 我现在不确定该去哪个论坛 因为我没有在任何地方获得帮助 1 我将通过终端并运行sudo rhc setup 我之所以使用sudo是因为没有它就无法进行下一步 2
  • 使用 git diff,如何获取添加和修改的行号?

    假设我有一个文本文件 alex bob matrix will be removed git repo 我已将其更新为 alex new line here another new line bob matrix git 在这里 我添加了行
  • wget ssl 警报握手失败

    我尝试从 https 站点下载文件并不断收到以下错误 OpenSSL error 14077410 SSL routines SSL23 GET SERVER HELLO sslv3 alert handshake failure Unab
  • 列出AWS S3存储桶中的所有对象

    我试图弄清楚如何在 Swift 中列出 AWS S3 存储桶中的所有对象 我似乎无法在互联网上的任何地方找到信息 但也许我看起来不够努力 如果有人可以向我推荐允许我执行此操作的代码 那就太好了 不知道你是否还需要它 但你可以 let cre
  • 如何在delphi 7中将unicode字符转换为ascii代码?

    是的 我们正在谈论 ASCII 代码 抱歉 我不是这里的 Delphi 开发人员 对于 Delphi 7 我会得到Mike Lischke 的免费 Unicode 库 http www soft gems net index php lib
  • 像#include 这样的预处理器指令只能放在程序代码的顶部吗?

    我已经用过 pragma函数内的指令没有错误或警告 特别是 pragma pack 但是下面的代码显示了警告incompatible implicit declaration of built in function printf int
  • 四人帮 - 设计模式 - 这些模式示例是否以过时的方式编码?

    所以为了澄清我的问题 臭名昭著的 GoF 书中的每个模式 设计模式 可重用的面向对象软件的元素 有 C 代码示例 这些是最新的吗 或者现在的 C 代码看起来有很大不同吗 我这么问是因为当我发布带有最后一个问题的代码时 许多 C 开发人员告诉
  • 九补丁与矢量图形

    我正在学习 Android UI 但不清楚为什么人们在可以使用矢量图形的情况下使用九个补丁 因为它们是可扩展的 不会出现任何像素退化 我是 Android 的初学者 所以我希望我在这里不会遗漏任何东西 但似乎构建矢量图形并使用它们会更容易
  • 为什么部分应用函数会延迟 Scala 中的类实例化?

    想象一下这段代码 class Foo println in Foo def foo a Int a 1 现在 如果我们调用 new Foo foo 将按预期创建 Foo 类的实例 in Foo res0 Int gt Int