选项GenTraversableOnce?

Kar*_*lek 17 scala

我很迷惑.在TraversableLike,有一个flatMap签名功能

flatMap[B](f: (A) ? GenTraversableOnce[B]): Iterable[B]

但是,我可以这样使用它

scala> Iterable(1,2,3,4,5).flatMap{i=>if (i%2==0) {None} else {Some(i)}}
res1: Iterable[Int] = List(1, 3, 5)
Run Code Online (Sandbox Code Playgroud)

为什么可能?怎么Option转换成GenTraversableOnce?它似乎不是一个子类......

Dan*_*ral 19

正如您在类图(*)中看到的那样,Option它不是子类GenTraversableOnce,但是有一个隐式转换可用Iterable,这是一个GenTraversableOnce.

在此输入图像描述

(*)是的,好吧,我作弊了.Scaladoc上没有类图...但它们应该是明天!:-)


Edm*_*984 16

实际上默认情况下从Some [X]到GenTraversableOnce [X]进行隐式转换.这在REPL中测试非常简单

scala>  implicitly[Function[Some[Int],GenTraversableOnce[Int]]]
res1: Some[Int] => scala.collection.GenTraversableOnce[Int] = <function1>

scala> implicitly[Some[Int] => GenTraversableOnce[Int]] // alternative syntax
res2: Some[Int] => scala.collection.GenTraversableOnce[Int] = <function1>
Run Code Online (Sandbox Code Playgroud)

事实上,这是在对象Option中定义的.内部scala包:

object Option {
  /** An implicit conversion that converts an option to an iterable value
   */
  implicit def option2Iterable[A](xo: Option[A]): Iterable[A] = xo.toList

  /** An Option factory which creates Some(x) if the argument is not null,
   *  and None if it is null.
   *
   *  @param  x the value
   *  @return   Some(value) if value != null, None if value == null
   */
  def apply[A](x: A): Option[A] = if (x == null) None else Some(x)

  /** An Option factory which returns `None` in a manner consistent with
   *  the collections hierarchy.
   */
  def empty[A] : Option[A] = None
}
Run Code Online (Sandbox Code Playgroud)

option2Iterable正是您所寻找的.您还可以看到为什么在REPL中进行测试时可以看到GenTraversableOnce的实现是一个列表.

如果您正在寻找在没有做任何事情的情况下自动导入的隐式转换(比如您可以隐式使用REPL中看到的那个),您必须查看:

  • Predef.scala
  • 该类的伴随对象