Scala 中的右关联方法有什么好处?

2023-12-06

我刚刚开始使用 Scala,并且刚刚了解了如何创建方法右结合(与更传统的左结合性在命令式面向对象语言中很常见)。

起初,当我看到示例代码时consScala 中的列表,我注意到每个示例总是在右侧有列表:

println(1 :: List(2, 3, 4))
newList = 42 :: originalList

然而,即使一遍又一遍地看到这个,我也没有多想,因为我(当时)不知道::是一个方法List。我只是假设它是一个运算符(同样是 Java 中运算符的意义),并且关联性并不重要。事实是List总是出现在示例代码的右侧似乎很巧合(我认为这可能只是“首选样式”)。

现在我更清楚了:它必须这样写,因为::是右结合的。

我的问题是,能够定义右关联方法有什么意义?

纯粹是出于审美原因,还是在某些情况下右关联实际上比左关联有某种好处?

从我(新手)的角度来看,我真的不明白如何

1 :: myList

比什么更好

myList :: 1

但这显然是一个微不足道的例子,我怀疑这是一个公平的比较。


简而言之,右关联性可以通过使程序员键入的内容与程序实际执行的内容一致来提高可读性。
所以,如果你输入 '1 :: 2 :: 3',你会得到一个 List(1, 2, 3) 返回,而不是以完全不同的顺序返回一个 List。
那是因为'1 :: 2 :: 3 :: Nil' 实际上是

List[Int].3.prepend(2).prepend(1)

scala> 1 :: 2 :: 3:: Nil
res0: List[Int] = List(1, 2, 3)

这是两者:

  • 更具可读性
  • 更高效(O(1) 为prepend,与假设的 O(n) 相比append method)

(温馨提示,摘自书中Scala 编程)
如果一个方法用在运算符表示法中,例如a * b,该方法在左侧操作数上调用,如下所示a.*(b)— 除非方法名称以冒号结尾。
如果方法名称以冒号结尾,则在右侧操作数上调用该方法。
因此,在1 :: twoThree, the ::方法被调用于twoThree,传入 1,如下所示:twoThree.::(1).

对于List来说,它起到了追加操作的作用(列表好像是追加在‘1’后面,形成‘1 2 3',实际上它是 1前置的到列表)。
类 List 不提供真正的追加操作,因为追加到列表所需的时间随着列表的大小线性增长,而前面加上 :: 需要恒定的时间.
myList :: 1会尝试将 myList 的整个内容添加到“1”,这比将 1 添加到 myList 更长(如“1 :: myList')

注意:无论运算符具有何种结合性,其操作数都是 总是从左到右评估。
因此,如果 b 是一个表达式,不仅仅是对不可变值的简单引用,那么 a ::: b 更准确地被视为以下块:

{ val x = a; b.:::(x) }

在这个块中,a仍然先于b进行评估,然后是本次评估的结果 作为操作数传递给 b 的 ::: 方法。


为什么要区分左联想和右联想方法呢?

这允许保持通常的左关联操作的外观('1 :: myList') 在实际对正确的表达式应用操作时,因为;

  • 它更有效率。
  • 但使用逆关联顺序('1 :: myList' vs. 'myList.prepend(1)')

据我所知,正如你所说,“语法糖”。
请注意,在以下情况下foldLeft,例如,他们可能有有点远了(与 '/:' 右结合运算符等价)


为了包含您的一些评论,稍微改写一下:

如果你考虑一个“追加”函数,左关联,那么你会写“oneTwo append 3 append 4 append 5'.
但是,如果将 3、4 和 5 附加到 oneTwo(您可以按照其编写方式进行假设),则复杂度为 O(N)。
如果用于“追加”,则与“::”相同。但事实并非如此。它实际上是为了“前置”

这意味着'a :: b :: Nil'是为了'List[].b.prepend(a)'

如果 '::' 放在前面但仍保持左关联,则结果列表的顺序将是错误的。
您希望它返回 List(1, 2, 3, 4, 5),但最终会返回 List(5, 4, 3, 1, 2),这可能是程序员意想不到的。
那是因为,您所做的按照左关联顺序应该是:

(1,2).prepend(3).prepend(4).prepend(5) : (5,4,3,1,2)

因此,右关联性使代码与返回值的实际顺序相匹配。

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

Scala 中的右关联方法有什么好处? 的相关文章

  • 如何从 Scala repl 中取消导入隐式?

    是否可以从 repl 中取消导入隐式内容 说我做这样的事情 scala gt import scala math BigInt import scala math BigInt scala gt implicits 2 implicit m
  • 如何在 Akka Stream 中记录流量?

    我有一个带有单个流 图的 Akka Stream 应用程序 我想测量源头的流量并每 5 秒记录一次 例如 在过去 5 秒内收到 3 条消息 我尝试过 someOtherFlow groupedWithin Integer MAX VALUE
  • 简单的 Scala actor 问题

    我确信这是一个非常简单的问题 但很不好意思地说我无法理解它 我有一个 Scala 值列表 我想使用演员来并行地对每个值进行一些 外部 调用 我想等到所有值都已处理完毕 然后继续 没有共享值被修改 有人可以建议吗 Thanks Scala 中
  • scala.collection.breakOut 与视图

    这个答案 https stackoverflow com a 1716558 936869描述如何scala collection breakOut可用于防止创建浪费的中间集合 例如 这里我们创建一个中间体Seq String String
  • Spark:用列的平均值替换数据框中的空值

    如何创建 UDF 以编程方式将每列中 Spark 数据框中的空值替换为列平均值 例如 在示例中 数据 col1 空值的值为 2 4 6 8 5 5 5 示例数据 col1 col2 col3 2 null 3 4 3 3 6 5 null
  • 如何在Dotty中使用given?

    我在看Dotty下的文档Contextual Abstractions页面 我看到了Given Instances 给定实例 或者简单地 给定 定义了 规范 值 用于合成给定子句的参数的某些类型 例子 trait Ord T def com
  • IntelliJ IDEA Scala 插件问题

    我对新的 Intellij IDEA 10 和 Scala 插件有疑问 当我在 Scala 源文件中输入任何内容时 编辑器会永久冻结 在其他文件 java 和其他 编辑器中效果很好 结构视图 scala 检查和显示成员功能已关闭 堆大小增加
  • 如何检查字符串中是否包含某个字符?

    我想检查字符串是否包含该字符 我正在编写一个刽子手代码 例如 下面是要猜测的单词 scala 但看起来像 至用户 假设用户输入字母 a 那么它一定看起来像 a a def checkGuess if result contains user
  • Scala:在运行时获取 mixin 接口

    我需要在运行时从给定的类获取所有接口 全部加载在类加载器中 例如 如果一个类是这样声明的 trait B trait C trait D class A extends B with C with D 我想在运行时获取这些信息 A 取决于
  • Scala:具有复杂结构的树插入尾递归

    我正在 scala 中创建自定义对象树 并且我的插入方法引发堆栈溢出 因为它不是尾递归 但是 我不太清楚如何使其尾递归 我见过使用 累加器 变量的相关示例 但它们要么是只能相乘和覆盖的整数之类的东西 要么是我在适应树时遇到困难的列表 这是我
  • 使用原始类型模拟案例类

    考虑以下类型结构 trait HasId T def id T case class Entity id Long extends HasId Long 比方说 我们想在一些测试中模拟实体类 val entityMock mock Enti
  • 使用 Akka 玩 2.5 - 找不到参数超时的隐式值:akka.util.Timeout

    我正在尝试使用 Play 2 5 测试 Akka 但遇到了一个似乎无法解决的编译错误 我正在关注 Play 文档中的此页面 https playframework com documentation 2 5 x ScalaAkka http
  • 使用 Spray-json 解析简单数组

    我正在尝试 但失败了 了解 Spray json 如何将 json feed 转换为对象 如果我有一个简单的 key gt value json feed 那么它似乎可以正常工作 但是我想要读取的数据出现在如下列表中 name John a
  • 通用特征的隐式转换

    我正在实现一个数据结构 并希望用户能够使用任何类型作为密钥 只要他提供一个合适的密钥类型来包装它 我有这个关键类型的特质 这个想法是进行从基类型到键类型的隐式转换 反之亦然 实际上 只使用基类型 该特征看起来像这样 trait Key T
  • Java 表达式树 [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 是否有相当于 net的 LINQ 下的表达式树JVM 我想实现一些类似 LINQ 的代码结构Scala
  • 使用 Spark DataFrame 获取组后所有组的 TopN

    我有一个 Spark SQL DataFrame user1 item1 rating1 user1 item2 rating2 user1 item3 rating3 user2 item1 rating4 如何按用户分组然后返回TopN
  • 缓存 Slick DBIO 操作

    我正在尝试加快 SELECT FROM WHERE name 的速度Play 中的查询类型 Scala 应用程序 我正在使用 Play 2 4 Scala 2 11 play slick 1 1 1 包 该软件包使用Slick 3 1版本
  • Scala 中的 Shapeless 结构编程:如何正确使用 SYB 实现?

    我想使用SYB http research microsoft com en us um people simonpj papers hmap 实施于无形图书馆 https github com milessabin shapeless编写
  • Scala 特性:val/def 和 require

    下面的代码抛出IllegalArgumentException trait T val x Long require x gt 0 object T extends App val y new T val x 42L 而以下情况则不然 tr
  • 使用 scala 在 Flink 中进行实时流预测

    弗林克版本 1 2 0斯卡拉版本 2 11 8 我想使用 DataStream 来使用 scala 中的 flink 模型进行预测 我在使用 scala 的 flink 中有一个 DataStream String 其中包含来自 kafka

随机推荐

  • 如何使用默认 R 安装通过 conda 安装 rpy2

    我在 Ubuntu Linux 上使用 Anaconda Python 发行版 并希望在 IPython 笔记本中使用 R 魔法 有没有办法使用 conda 发行版安装 rpy2 并使用我当前在 usr bin R 的默认 R 安装 我的目
  • codeigniter 在 find_in_set 中添加 IS NULL

    通过生成查询时代码点火器框架 this gt db gt select id memo sent to sent by read by date gt from memos gt where FIND IN SET 1 sent to gt
  • Zxing有时会从条形码中获取错误的数据

    我知道这可能是一个相当简单的问题 我们还可以设置 Zxing 扫描的条形码格式 如下所示 1 intent putExtra SCAN MODE QR CODE MODE or any other format 如果我们这样做 2 inte
  • 什么时候优化为时过早? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心以获得指导 我看到这个词用得很多 但我
  • Xcode 5:代码签名权利错误

    我已经构建了一个支持 IOS 7 的新应用程序 我获得了新的 XCode 5 GM 并尝试使用我的新配置文件和分发证书来签署我的应用程序 但我在分发时遇到了问题 我不断收到以下错误 无效的代码签名权利 您的应用程序中的权利 包签名与包含在包
  • 拆分一列字符向量并返回一个列表

    我有以下内容数据框 df lt data frame Sl No c 1 6 Variable c a a b a b c b c b c Sl No Variable 1 a 2 a b 3 a b c 4 b 5 c 6 b c 我想将
  • os/exec StdoutPipe 带颜色

    我正在制作一个包装纸我的世界使用 Go 的服务器控制台 它使用 os exec 运行服务器和 process StdoutPipe 以获取子进程的实时输出 但是 由于某种原因我无法让它显示颜色 当我直接从终端运行服务器时 颜色可以工作 但当
  • 如何忽略包含在我的yarn.lock 文件中的包?

    因此 在我的 package json 中 我有一堆 npm 库 以及一个从 git ssh url 拉入的私有存储库 该存储库需要始终是最新版本 该yarn lock添加了git sha和yarn升级等不会获取最新的 基本上 鉴于此 de
  • 如何通过 Socket 连接接收大数据流 - 没有 TCPClient

    我有一个问题 我想通过 SocketConnection 发送一个大字符串 但我无法立即接收该字符串 因为网络限制为 1500 字节 那么如何在不使用 TCPClient 的情况下通过 Socket 接收所有字节 或者这是不可能的 publ
  • 如何在类路径中使用嵌入表达式

    我试图将文件的绝对值传递给类路径的读取函数 如果我传递绝对路径和类路径 它就可以正常工作 但是当我传递嵌入表达式时它不起作用 我的代码如下 Scenario create swagger first RAD 给定 url 应用服务器 给定参
  • 在 PrintDialog 中以编程方式选择打印机

    我在 Windows 窗体中有一个 Web 浏览器控件 它加载一个 HTML 文件 我希望能够为用户提供将其另存为 PDF 文件的选项 如果用户安装了 CutePDF Writer 那么我想我可以通过编程方式从打印对话框中选择它并将其另存为
  • jQuery 中的 this 和 $(this) 有什么区别?

    jQuery 中的 this 和 this 有什么区别 我什么时候应该使用哪个 p each function this id this attr id 如果您考虑上面的函数 jQuery 将循环访问页面上的每个段落元素 并通过将 this
  • 如何可靠地猜测 MacRoman、CP1252、Latin1、UTF-8 和 ASCII 之间的编码 [重复]

    这个问题在这里已经有答案了 在工作中 似乎每周都会遇到一些与编码相关的忧虑 灾难或灾难 该问题通常源于程序员认为他们可以在不指定编码的情况下可靠地处理 文本 文件 但你不能 因此决定从今以后禁止文件名以以下结尾 txt or text 人们
  • 错误“‘git’未被识别为内部或外部命令”

    我安装了 Windows 版 Git 但是当我尝试使用git命令提示符中的命令 我收到以下错误 git is not recognized as an internal or external command operable progra
  • 是否可以从列表中的项目获取索引?

    我的意思是 我有一个列表框 我将列表放入 itemsSource 属性中 我还想显示它的绑定中的索引 我不知道这在 WPF 中是否可行 谢谢 有几种方法可以做到这一点 包括使用 AlternationIndex 的一些解决方法 但是 由于我
  • iOS,将文件从收件箱文件夹复制到文档路径

    我启用了文档类型以将文件从其他应用程序导入或复制到我的应用程序 我有一些疑问 1 应该在哪里创建将文件从收件箱移动到文档目录的方法 这是正确的地方吗 func applicationWillEnterForeground applicati
  • 将语音输出解析为 JSON 以调用应用程序 API

    这是一个想法 我们有带有公开的 Restful API 的 Web 应用程序 它接受 json 现在 如何使用 Google 语音 API 获取用户语音输入 将其转换为文本 然后以某种方式将该文本转换为 API 所需的 JSON 然后使用
  • 未找到样式属性 attr/@attr/minTextSize

    我长期以来一直在尝试找出问题所在 但不幸的是无法 If I do android enableAapt2 true 代码工作正常 但是删除相同的代码 应该是强制的 会抛出错误 incremental mergeDevDebugResourc
  • 如何合并两个文件?

    我有两个文件 File 1 7118 7457 7591 7539 8001 File 2 5003 5008 5011 5026 5028 5029 5031 我需要的输出 7118 5003 7457 5003 7591 5003 75
  • Scala 中的右关联方法有什么好处?

    我刚刚开始使用 Scala 并且刚刚了解了如何创建方法右结合 与更传统的左结合性在命令式面向对象语言中很常见 起初 当我看到示例代码时consScala 中的列表 我注意到每个示例总是在右侧有列表 println 1 List 2 3 4