何时使用scala triple caret(^^^)vs双插入符号(^^)和into方法(>>)

bje*_*001 6 scala parser-combinators

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

Tra*_*own 17

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

val fullBox: Option[String] = Some("13")
val emptyBox: Option[String] = None
Run Code Online (Sandbox Code Playgroud)

Option是monadic,这意味着(部分)我们可以map对其内容执行一个功能:

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

scala> emptyBox.map(_.length)
res1: Option[Int] = None
Run Code Online (Sandbox Code Playgroud)

关心是否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
Run Code Online (Sandbox Code Playgroud)

Optionmonadic 这一事实也意味着我们可以应用于Option[A]一个函数,它接受一个A并返回一个Option[B]并得到一个Option[B].对于此示例,我将使用一个尝试将字符串解析为整数的函数:

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

现在我们可以写下面的内容:

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
Run Code Online (Sandbox Code Playgroud)

这一切都与你的问题有关,因为Parser它也是monadic,它有map和flatMap方法的工作方式非常相似Option.它还有一堆令人困惑的运算符(我之前已经大肆宣传过),包括你提到的运算符,这些运算符只是map和的别名flatMap:

(parser ^^ transformation) == parser.map(transformation)
(parser ^^^ replacement) == parser.map(_ => replacement)
(parser >> nextStep) == parser.flatMap(nextStep)
Run Code Online (Sandbox Code Playgroud)

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

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
}
Run Code Online (Sandbox Code Playgroud)

每个解析器的行为方式与上述Option示例之一相同.