用 def 方法和 val 函数展平 Vs flatMap

flatten Vs flatMap with def method and val function

flatten Vs flatMap with def method and val function:

我定义了一个名为 toInt:

的 def 方法
  def toInt(s: String): Option[Int] = {
    try {
      Some(Integer.parseInt(s.trim))
    } catch {
      case e: Exception => None
    }
  }

并且此方法适用于 flatten 和 flatMap,如下所示:

//using toInt method
val x = 1.to(5).toList
val y = List("a")
val z = x ++ y
val q = z.map(_.toString)

//using map and flatten
println(q.map(toInt).flatten)
//using flatMap
println(q.flatMap(toInt))

现在我在函数中使用 val 定义了相同的 toInt 功能(如在 def 方法中)"tooInt":

val tooInt: String => Option[Int] = s => {
  try {
    Some(Integer.parseInt(s.trim))
  } catch {
    case c: Exception => None
  }
}

这适用于展平但不适用于 flatMap,如下所示:

//using map and flatten
 println(q.map(tooInt).flatten)
 //using flatMap // this has error
 **println(q.flatMap(tooInt))**

你能帮我理解一下吗?

此致, 基兰

您需要稍微帮助编译器进行扩展才能使其工作:

q.flatMap(s => tooInt(s))

这一切都归结为我们在 Option.scala 中定义了一个隐含的 option2Iterable。当您首先 map 然后 flatten 时,Option[Int] 已经在范围内并且可以应用隐式。但是当你 flatMap 时,编译器必须首先将 tooInt 扩展为 s => tooInt(s) 然后应用隐式解析,但这是行不通的。为什么它不起作用?因为编译器寻找类型的隐式:

pt=(=> String => Option[Int]) => (String => scala.collection.GenTraversableOnce[?])

不存在。反之,先将toInt方法展开为函数类型,然后隐式搜索Option[Int]:

-- toInt : pt=String => scala.collection.GenTraversableOnce[?] BYVALmode-EXPRmode-POLYmode (site: value r in X)
|    |    |    |    |    |    |-- { ((s: String) => toInt(s)) } : pt=String => scala.collection.GenTraversableOnce[?] BYVALmode-EXPRmode-POLYmode (site: value r in X)
|    |    |    |    |    |    |    |-- ((s: String) => toInt(s)) : pt=String => scala.collection.GenTraversableOnce[?] BYVALmode-EXPRmode-POLYmode (site: value r in X)
|    |    |    |    |    |    |    |    |-- (s: String)Option[Int] : pt=scala.collection.GenTraversableOnce[?] EXPRmode (site: value $anonfun in X)
|    |    |    |    |    |    |    |    |    |-- s : pt=String BYVALmode-EXPRmode (site: value $anonfun in X)
|    |    |    |    |    |    |    |    |    |    \-> String
|    |    |    |    |    |    |    |    |    [search #3] start `(s: String)Option[Int]`, searching for adaptation to pt=Option[Int] => scala.collection.GenTraversableOnce[?] (silent: value $anonfun in X) implicits disabled
|    |    |    |    |    |    |    |    |    [search #3] considering scala.this.Option.option2Iterable

我们在反编译代码中也可以看到:

val r: scala.collection.immutable.IndexedSeq[Int] = q.flatMap[Int, scala.collection.immutable.IndexedSeq[Int]]({
    {
      final <artifact> def $anonfun$main(s: String): Iterable[Int] = scala.this.Option.option2Iterable[Int](toInt(s));
      ((s: String) => $anonfun$main(s))
    }
  }, immutable.this.IndexedSeq.canBuildFrom[Int]());