Scala - map和flatMap之间的区别

时间:2017-07-30 14:43:43

标签: scala functional-programming

有人可以教我mapflatMap的财产使用案例吗?

Option案例中,我知道这两种方法都有每个签名,def map(A => B): Option[B]def flatMap(A => Option[B]): Option[B]

所以,我可以通过两种方式获得一些价值:

scala> val a = Some(1).map(_ + 2)
a: Option[Int] = Some(3)

scala> val a2 = Some(1).flatMap(n => Some(n + 2))
a2: Option[Int] = Some(3)

当我写一个方法:def plusTwo(n: Int)时,

之间是否有任何区别
def plusTwo(n: Int): Int = n + 2
Some(1).map(plusTwo)

def plusTwo(n: Int): Option[Int] = Some(n + 2)
Some(1).flatMap(plusTwo)

flatMap可以转换为for-comprehension,并且几乎所有方法都返回值Option包裹好吗?

2 个答案:

答案 0 :(得分:2)

假设您有一个列表:

    let widthContr = NSLayoutConstraint(item: unitControl,
                                        attribute: NSLayoutAttribute.width,
                                        relatedBy: NSLayoutRelation.equal,
                                        toItem: cell,
                                        attribute: NSLayoutAttribute.notAnAttribute,
                                        multiplier: 1,
                                        constant: 0.5)
    cell.addConstraints([widthContr])

现在让我们继续你的例子吧。假设我们有一个返回选项的函数:

val names = List("Benny", "Danna", "Tal")
names: List[String] = List(Benny, Danna, Tal)

map函数的工作原理是将函数应用于列表中的每个元素:

def f(name: String) = if (name contains "nn") Some(name) else None

另一方面,flatMap应用一个函数,该函数返回列表中每个元素的序列,并将结果展平为原始列表

names.map(name => f(name))
List[Option[String]] = List(Some(Benny), Some(Danna), None)

如您所见,flatMap删除了Some / None图层并仅保留原始列表。

答案 1 :(得分:0)

您的函数plusTwo会返回所有输入的有效结果,因为您可以向任何Int添加2。

无需定义它返回Option [Int],因为永远不会返回None值。这就是你使用Option.map

这类功能的原因

但并非所有函数都对每个输入都有有意义的结果。例如,如果你的函数按函数参数划分某个数字,那么将零传递给该函数是没有意义的。

假设我们有一个功能:

def divideTenBy(a: Int): Double

当你用零调用它时,抛出ArithmeticException。然后你必须记住捕获这个异常,这样才能使我们的函数更容易出错。

def divideTenBy(a: Int): Option[Double] = if (a == 0) None else Some(10 / a)

使用这些函数可以使用flatMap,因为在可选(左操作数)中可以有'None'值,或者给定的函数可以返回None。

现在您可以安全地将此函数映射到任何值:

scala> None.flatMap(divideTenBy)
res9: Option[Double] = None

scala> Some(2).flatMap(divideTenBy)
res10: Option[Double] = Some(5.0)

scala> Some(0).flatMap(divideTenBy)
res11: Option[Double] = None