何时使用 scala 三重插入符 (^^^) 与双插入符 (^^) 和 into 方法 (>>)

2023-11-26

有人可以解释在设计 scala 解析器组合器时如何以及何时使用三重插入符 ^^^ (与双插入符 ^^)吗?以及何时/如何使用 parser.into() 方法 (>>)。


我将从一个使用 Scala 的示例开始Option类型,在一些重要方面类似于Parser,但可以更容易推理。假设我们有以下两个值:

val fullBox: Option[String] = Some("13")
val emptyBox: Option[String] = None

Option是一元的,这意味着(部分)我们可以map其内容的函数:

scala> fullBox.map(_.length)
res0: Option[Int] = Some(2)

scala> emptyBox.map(_.length)
res1: Option[Int] = None

只关心是否Option是否已满,在这种情况下我们可以使用map使用忽略其参数的函数:

scala> fullBox.map(_ => "Has a value!")
res2: Option[String] = Some(Has a value!)

scala> emptyBox.map(_ => "Has a value!")
res3: Option[String] = None

事实是Option是一元的也意味着我们可以应用于Option[A]一个函数,它需要一个A并返回一个Option[B]并得到一个Option[B]。在本示例中,我将使用一个尝试将字符串解析为整数的函数:

def parseIntString(s: String): Option[Int] = try Some(s.toInt) catch {
  case _: Throwable => None
}

现在我们可以编写以下内容:

scala> fullBox.flatMap(parseIntString)
res4: Option[Int] = Some(13)

scala> emptyBox.flatMap(parseIntString)
res5: Option[Int] = None

scala> Some("not an integer").flatMap(parseIntString)
res6: Option[Int] = None

这都与你的问题相关,因为Parser也是一元的,并且它有map and flatMap方法的工作方式与上面的方法非常相似Option。它还有一堆令人困惑的运算符(其中我之前也吐槽过),包括你提到的那些,这些运算符只是别名map and flatMap:

(parser ^^ transformation) == parser.map(transformation)
(parser ^^^ replacement) == parser.map(_ => replacement)
(parser >> nextStep) == parser.flatMap(nextStep)

例如,您可以编写以下内容:

object MyParser extends RegexParsers {
  def parseIntString(s: String) = try success(s.toInt) catch {
    case t: Throwable => err(t.getMessage)
  }

  val digits: Parser[String] = """\d+""".r
  val numberOfDigits: Parser[Int] = digits ^^ (_.length)
  val ifDigitsMessage: Parser[String] = digits ^^^ "Has a value!"
  val integer: Parser[Int] = digits >> parseIntString
}

每个解析器的行为方式相当于其中之一Option上面的例子。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

何时使用 scala 三重插入符 (^^^) 与双插入符 (^^) 和 into 方法 (>>) 的相关文章

随机推荐