【问题标题】:GenericTraversableTemplate::flatten. What kind of magic does it do?GenericTraversableTemplate::flatten。它有什么样的魔法?
【发布时间】:2016-11-18 23:56:03
【问题描述】:

我试图了解flatten 方法有什么魔力。这是一个示例表单this article

def toInt(s: String): Option[Int] = {
    try {
        Some(Integer.parseInt(s.trim))
    } catch {
        // catch Exception to catch null 's'
        case e: Exception => None
    }
}

scala> val strings = Seq("1", "2", "foo", "3", "bar")
strings: Seq[java.lang.String] = List(1, 2, foo, 3, bar)

scala> strings.map(toInt)
res0: Seq[Option[Int]] = List(Some(1), Some(2), None, Some(3), None)

scala> val flattenResult = mapResult.flatten
flattenResult: Seq[Int] = List(1, 2, 3)

哇。它看起来像一些奇迹。 flatten 方法如何知道我们不应该将Nones 添加到结果集合中。它的实现方式并不明显:

def flatten[B](implicit asTraversable: A => /*<:<!!!*/ GenTraversableOnce[B]): CC[B] = {
    val b = genericBuilder[B]
    for (xs <- sequential)
      b ++= asTraversable(xs).seq
    b.result()
  }

你能不能解释一下它的含义...我的意思是它一般有什么作用?也许它确实知道,None 是一个 monadic 值,并使用它的一些“monadic”方法。但这只是猜测。

【问题讨论】:

    标签: scala collections flatten


    【解决方案1】:

    Flatten 方法隐式接收一个方法,该方法能够采用 A(在我们的例子中为 Option)并将其转换为 GenTraversableOnce。

    Option 对象中定义了一个隐式方法:

    implicit def option2Iterable[A](xo: Option[A]): Iterable[A] = xo.toList
    

    并且 toList 在返回 Iterable 之前检查对象是否为空:

    def toList: List[A] =
        if (isEmpty) List() else new ::(this.get, Nil)
    

    意思是我们在 None 上应用 option2Iterable 时会得到一个空列表。

    所以行:

    b ++= asTraversable(xs).seq
    

    实际上是在对 None 或具有 Some 值的列表执行时向 b 添加一个空 seq 以防 Some。

    这就是为什么您在展平输出中看不到 None / Some 对象,而只能看到 Some 对象的值。

    【讨论】:

    【解决方案2】:

    您会看到 flatten 可以在包含可转换为 GenTraversableOnce 的值的集合上调用:

    def flatten[B](implicit asTraversable: A => GenTraversableOnce[B]): CC[B]
    

    由于在Option companion object 中存在到Iterable 的隐式转换,它应该有资格成为flatten-ed(IterableGenTraversableOnce 的子类型)。

    它将Option转换为List,它的实现很明显..

    如果我错了,请纠正我,我对 Scala 的集合实现感到不知所措......

    【讨论】:

    • 我唯一的更正是s/it's/its/。另外,我不确定有什么明显的。另一个答案也显示了代码,这也不明显。一路下来都不是很明显。
    • 非常有趣。我无法想象这完全是一种隐式转换。
    猜你喜欢
    • 2010-12-20
    • 2011-01-28
    • 1970-01-01
    • 1970-01-01
    • 2011-05-18
    • 2013-02-04
    • 1970-01-01
    • 2018-08-24
    • 2012-05-14
    相关资源
    最近更新 更多