为什么 Scala Option.tapEach return Iterable,而不是 Option?
Why does Scala Option.tapEach return Iterable, not Option?
Option.tapEach
的 scaladoc 声明“returns:与此 相同的逻辑集合”正如对名为在 tap
& foreach
之后。但是,它不是 return 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 进行验证)
是否有充分的理由 return Iterable
而不是 Option
,或者这只是被忽略了(最终可能会修复)?
似乎 Option
是否被认为是一个完整的集合有点像 Make Option extend IterableOnce #8038. I think the relevant comment 上的讨论所表明的蠕虫是
So it can definitely be a IterableOnce
because you can get an iterator
of zero to one elements. But it can't be a Iterable
because you you
can't implement fromSpecific(c: IterableOnce[A]): K
without throwing
away data.
然而 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
通过隐式转换提供
This member is added by an implicit conversion from Option[A]
to Iterable[A]
performed by method option2Iterable
in scala.Option
.
即
option2iterable(Option(5)).tapEach(_ => ())
因此 Iterable[Int]
return 类型。
还要考虑以下note
Many of the methods in here are duplicative with those in the
Traversable hierarchy, but they are duplicated for a reason: the
implicit conversion tends to leave one with an Iterable in situations
where one could have retained an 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
的 scaladoc 声明“returns:与此 相同的逻辑集合”正如对名为在 tap
& foreach
之后。但是,它不是 return 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 进行验证)
是否有充分的理由 return Iterable
而不是 Option
,或者这只是被忽略了(最终可能会修复)?
似乎 Option
是否被认为是一个完整的集合有点像 Make Option extend IterableOnce #8038. I think the relevant comment 上的讨论所表明的蠕虫是
So it can definitely be a
IterableOnce
because you can get an iterator of zero to one elements. But it can't be aIterable
because you you can't implementfromSpecific(c: IterableOnce[A]): K
without throwing away data.
然而 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
This member is added by an implicit conversion from
Option[A]
toIterable[A]
performed by methodoption2Iterable
inscala.Option
.
即
option2iterable(Option(5)).tapEach(_ => ())
因此 Iterable[Int]
return 类型。
还要考虑以下note
Many of the methods in here are duplicative with those in the Traversable hierarchy, but they are duplicated for a reason: the implicit conversion tends to leave one with an Iterable in situations where one could have retained an 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)