[英]flatten Vs flatMap with def method and val function
flatten Vs flatMap with def method and val function: 使用def方法和val函数展平Vs flatMap:
I defined a def method called toInt : 我定义了一个名为toInt的def方法:
def toInt(s: String): Option[Int] = {
try {
Some(Integer.parseInt(s.trim))
} catch {
case e: Exception => None
}
}
And this method works fine with both flatten and flatMap as follows: 这个方法适用于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))
Now I defined the same toInt functionality(as in def method) using val in a function "tooInt": 现在我在函数“tooInt”中使用val定义了相同的toInt功能(如在def方法中):
val tooInt: String => Option[Int] = s => {
try {
Some(Integer.parseInt(s.trim))
} catch {
case c: Exception => None
}
}
This works fine with flatten but NOT with flatMap as shown below: 如下图所示这正常工作与扁平化,但不与flatMap:
//using map and flatten
println(q.map(tooInt).flatten)
//using flatMap // this has error
**println(q.flatMap(tooInt))**
Could you please help me in understanding this? 你能帮我理解一下吗?
Best Regards, Kiran 最诚挚的问候,Kiran
You need to help the compiler a little with expansion to make this work: 你需要通过扩展来帮助编译器做一些工作:
q.flatMap(s => tooInt(s))
It all boils down to the fact that we have an implicit option2Iterable
defined in Option.scala
. 这一切都归结为我们在
Option.scala
定义了一个隐含的option2Iterable
。 When you first map
and then flatten
, the Option[Int]
is already in scope and the implicit can be applied. 当您第一次
map
然后flatten
, Option[Int]
已经在范围内并且可以应用隐式。 But when you flatMap
, the compiler has to first expand tooInt
to s => tooInt(s)
and then apply the implicit resolution, but that doesn't work. 但是当你使用
flatMap
,编译器必须首先将tooInt
展开为s => tooInt(s)
,然后应用隐式解析,但这不起作用。 Why doesn't it work? 为什么不起作用? because the compiler looks for an implicit of type:
因为编译器会查找隐式类型:
pt=(=> String => Option[Int]) => (String => scala.collection.GenTraversableOnce[?])
Which doesn't exist. 哪个不存在。 On the contrary, the
toInt
method is first expanded into a function type, and then the implicit is searched for Option[Int]
: 相反,首先将
toInt
方法扩展为函数类型,然后在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
We can also see it in the decompiled code: 我们也可以在反编译代码中看到它:
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]());
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.