scala - 为什么 Scala Option.tapEach 返回 Iterable,而不是 Option?
问题描述
状态的scaladoc “返回:与此相同的逻辑集合”,正如以&命名的操作所期望的那样。但是,它不返回 a而是由 a 支持:Option.tapEach
tap
foreach
Option
Iterable
List
scala> import scala.util.chaining._
scala> Option(5).tap(_.foreach(_ => ()))
val res0: Option[Int] = Some(5)
scala> Option(5).tapEach(_ => ())
val res1: Iterable[Int] = List(5)
(已针对 Scala 2.13.5 和 3.0.0-RC1 进行了验证)
是否有充分的理由返回Iterable
而不是Option
,或者这只是被忽略了(最终可能会被修复)?
解决方案
正如Make Option extend IterableOnce #8038中的讨论所表明的那样,似乎是否Option
将完整集合视为一个蠕虫罐头。我认为相关评论是
所以它绝对可以是 a
IterableOnce
因为你可以获得一个零到一个元素的迭代器。但这不可能是因为如果不丢弃数据Iterable
就无法实现。fromSpecific(c: IterableOnce[A]): K
然而在其定义中tapEach
使用fromSpecific
override def tapEach[U](f: A => U): C = fromSpecific(new View.Map(this, { (a: A) => f(a); a })
所以要记住的关键是Option
因为 Scala 2.13 是一个IterableOnce
但不是一个完整的Iterable
. IterableOnce
与 相比更小Iterable
,因此如果需要它的功能,则根据文档Iterable
通过隐式转换提供
该成员是通过隐式转换添加的,
Option[A]
由in 中Iterable[A]
的方法执行。option2Iterable
scala.Option
那是
option2iterable(Option(5)).tapEach(_ => ())
因此Iterable[Int]
返回类型。
还要考虑以下注释
这里的许多方法与 Traversable 层次结构中的方法是重复的,但它们之所以重复是有原因的:隐式转换往往会在可以保留选项的情况下留下一个 Iterable。
所以贡献者必须在 Option 中烘焙一个专门的版本来保留类型,或者我们可以提供我们自己的专门的扩展实现,比如
scala> implicit class OptionTapOps[A](v: Option[A]) {
| def tapEach[B](f: A => B): Option[A] = { v.foreach(f); v }
| }
class OptionTapOps
scala> Option(5).tapEach(_ => ())
val res11: Option[Int] = Some(5)
推荐阅读
- google-apps-script - 如何使用多个单元格值从 Google 工作表中查找值并发送电子邮件
- android - 当 Google Play 控制台设备目录中未显示特定设备品牌/型号时,如何排除它?
- python-3.x - 如何在将输入与Python中的字符串进行比较的循环中切换字符串的len []位置?
- java - 在 log4j2 中更改关键字的日志级别
- ios - 如何在应用程序中保存凭据以允许自动填充功能?
- hibernate - HIbernate - 表更新 - 允许一次更新一个请求
- windows - Powershell 不创建注册表项
- css - ReactJS 应用程序未加载自定义字体
- c# - C# 强制转换为仍在运行子方法的父级
- angular - npm install 和 ionic build 不会安装所有节点模块