2

为什么函数personFromParams返回None

  def personFromParams(p: Map[String, String]): Option[Person] =
    for {
      name <- p.get("name")
      ageStr <- p.get("age")
      age <- toInt(ageStr)
      validStr <- p.get("valid")
      valid <- toBool(validStr)
    } yield { println("personFromParams()"); new Person(name, age, valid) }

   def tryo[T](f: => T): Option[T] = try {Some(f)} catch {case _ => None}

   def toInt(s: String): Option[Int] = tryo(s.toInt);
   def toBool(s: String) = tryo(JBool.parseBoolean(s))

如果给 非数字值toInt,它会返回Nonefor age,但我不明白为什么在函数中捕获和处理异常时会toInt中断。fortryo

4

3 回答 3

3

因为for理解可以等效地写成这样

p.get("name").flatMap{
  name => p.get("age").flatMap {
    ageStr => toInt(ageStr).flatMap {
      age => p.get("valid").flatMap {
        validStr => p.get("valid").flatMap {
          validStr => toBool(validStr).map{
            valid => { println("personFromParams()"); new Person(name, age, valid) }
          } 
        }
      }
    }
  }
}

来自Option.flatMap的scala文档:

如果此选项非空,则返回将 f 应用于此选项的值的结果。如果此选项为空,则返回 None。与 map 略有不同的是, f 预计会返回一个 Option(可能是 None)。

于 2012-12-07T13:38:49.130 回答
2

它不会中断 for 执行。只是,当 scala 查找它应该遍历的年龄集合时,没有要遍历的元素。

请注意,for yield 等价于 map,嵌套 for yield 等价于 set product then map(不完全是,但你明白了)。如果输入集之一为空,则结果集也为空,对吗?

要解决这个问题,您只需删除通过 toInt(age) 的行,并将其放入构造函数参数中。

于 2012-12-07T13:32:58.583 回答
1
for { a <- Some(3) } println(a) // 3
for { a <- None } println(a)    // no output

这种行为是意料之中的,可以通过查看for编译器将 a 脱糖的表达式来解释。如果您-print在上面的代码片段上运行 Scala,您会看到循环被脱糖为forach

new Some(scala.Int.box(3)).foreach({...})
scala.None.foreach({...})

由于None代表一个空集合,所以没有什么可以foreach结束的。

于 2012-12-07T13:36:59.407 回答