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

标签 scala parser-combinators

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

最佳答案

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

val fullBox: Option[String] = Some("13")
val emptyBox: Option[String] = None
Option是 monadic,这意味着(部分)我们可以 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 is monadic 也意味着我们可以申请 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也是 monadic,它有 mapflatMap方法与 Option 上的方法非常相似.它还有一堆令人困惑的运算符(其中 I've ranted about before),包括你提到的那些,而这些运算符只是 map 的别名。和 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 中的一个相同上面的例子。

关于scala - 何时使用 scala 三重插入符 (^^^) 与双重插入符 (^^) 和 into 方法 (>>),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21259470/

相关文章:

arrays - 在 Scala 中初始化时如何强制数组的类型?

Scala PackratParser 忽略失败解析器

用于递归 bnf 的 Scala Parser Combinators 技巧?

scala - 语法规则的 def 或 val 或惰性 val ?

compiler-construction - Scalas/Haskells 解析器组合器是否足够?

scala - 如何从Spark中的Hbase表读取数据?

arrays - 为什么大型数组构造函数调用会破坏 Scala 编译器?

scala - 如何在 Play Framework 中创建多个自定义字段?

scala - Scala中的函数对象的varargs错误?

Scala 解析器组合器几乎是最后一个