为啥 Scala Option.tapEach 返回 Iterable,而不是 Option?
Posted
技术标签:
【中文标题】为啥 Scala Option.tapEach 返回 Iterable,而不是 Option?【英文标题】:Why does Scala Option.tapEach return Iterable, not Option?为什么 Scala Option.tapEach 返回 Iterable,而不是 Option? 【发布时间】:2021-07-05 03:28:23 【问题描述】:Option.tapEach
的 scaladoc 声明“返回:与此相同的逻辑集合”,正如以 tap
和 foreach
命名的操作所期望的一样。但是,它不会返回Option
,而是返回由List
支持的Iterable
:
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
,或者这只是被忽略了(最终可能会得到修复)?
【问题讨论】:
Option
没有自己的tapEach
实现,它继承自Iterable
。因此结果。
【参考方案1】:
Option
是否被认为是一个完整的集合似乎有点像Make Option extend IterableOnce #8038 的讨论所表明的那样。我认为相关的comment是
所以它绝对可以是
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
的功能,它会通过隐式转换根据 docs 提供
这个成员是由
Option[A]
的隐式转换添加的 到Iterable[A]
由option2Iterable
在scala.Option
中的方法执行。
那是
option2iterable(Option(5)).tapEach(_ => ())
因此Iterable[Int]
返回类型。
同时考虑以下note
这里的许多方法与 可遍历的层次结构,但它们被重复是有原因的: 在某些情况下,隐式转换往往会留下一个 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)
【讨论】:
谢谢,很好的解释!我想在 Option 中贡献一个专门的 tapEach 版本来保留类型。你有贡献的经验吗? ...我应该只创建一个拉取请求,还是应该首先有一个错误或拉取请求所指的其他东西? @Georg 我在 scala 贡献者的 gitter 频道上问过,他们说要在github.com/scala/scala-library-next打开 PR github.com/scala/scala-library-next/pull/80以上是关于为啥 Scala Option.tapEach 返回 Iterable,而不是 Option?的主要内容,如果未能解决你的问题,请参考以下文章
为啥 isset($this->var) 在我的 Codeigniter 模型中总是返回 false?
为啥scala maven工件对每个scala版本都有一个工件,而不是每个scala版本都有一个分类器?