1

我有这两个功能

  def pattern(s: String): Option[Pattern] =
try {
  Some(Pattern.compile(s))
} catch {
  case e: PatternSyntaxException => None
}

  def mkMatcher(pat: String): Option[String => Boolean] =
     pattern(pat) map (p => (s: String) => p.matcher(s).matches)

Map 是将给定函数应用于列表的每个元素的高阶函数。

现在我不知道地图是如何按照上述声明在这里工作的。

4

2 回答 2

2

Map 是将给定函数应用于列表的每个元素的高阶函数。

这是地图的一个不常见的限制性定义。

无论如何,它之所以有效,是因为它是由不坚持这一点的人定义的。

例如,有人写了类似于

sealed trait Option[+A] {
  def map[B](f: A => B): Option[B] = this match {
    case Some(value) => Some(f(value))
    case None => None
  }
}

作为标准库的一部分。这使得地图适用于Option[A]

定义它是因为映射多种数据结构而不仅仅是列表是有意义的。映射是应用于数据结构所包含的元素的转换。

它对每个元素应用一个函数。

Option[A]可以认为是一个微不足道的序列。它要么有零个元素,要么有一个元素。映射它意味着将函数应用于其元素(如果它有一个)。

现在,一直使用此工具可能没有多大意义,但在某些情况下它很有用。

例如,它是少数几种不同的方法之一,当它们存在时,可以启用For Expressions对类型进行操作。Option[A]可用于方便的表达式。

例如

val option: Option[Int] = Some(2)

val squared: Option[Int] = for {
  n <- option
  if n % 2 == 0
} yield n * n

有趣的是,这意味着filter也被定义在Option[A].

如果您只有一个简单的值,那么使用不太通用的构造可能会更清楚。

于 2018-02-22T06:44:05.810 回答
2

Map 的工作方式与其他集合类型(如 List 和 Vector)的工作方式相同。它将您的函数应用于集合的内容,可能会更改类型但保持集合类型相同。

在许多情况下,您可以将 Option 视为具有 0 或 1 个元素的集合。您可以对 Option 执行许多与其他集合相同的操作。

您可以修改值

var opt = Option(1)

opt.map(_ + 3)
opt.map(_ * math.Pi)
opt.filter(_ == 1)
opt.collect({case i if i > 0 => i.toString })

opt.foreach(println)

你可以测试这个值

opt.contains(3)
opt.forall(_ > 0)
opt.exists(_ > 0)
opt.isEmpty

使用这些方法,您很少需要使用 match 语句来取消选择选项。

于 2018-02-22T10:30:13.487 回答