何时使用 scala 三重插入符 (^^^) 与双重插入符 (^^) 和 into 方法 (>>) [英] When to use scala triple caret (^^^) vs double caret (^^) and the into method (>>)

查看:57
本文介绍了何时使用 scala 三重插入符 (^^^) 与双重插入符 (^^) 和 into 方法 (>>)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Can someone explain how and when to use the triple caret ^^^ (vs the double caret ^^) when designing scala parser combinators? And also when / how to use the parser.into() method (>>).

推荐答案

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

I'll begin with an example using Scala's Option type, which is similar in some important ways to Parser, but can be easier to reason about. Suppose we have the following two values:

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

Option 是 monadic,这意味着(部分)我们可以map 一个函数覆盖其内容:

Option is monadic, which means (in part) that we can map a function over its contents:

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

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

只关心 Option 是否已满的情况并不少见,在这种情况下,我们可以将 map 与忽略其参数的函数一起使用:

It's not uncommon to care only about whether the Option is full or not, in which case we can use map with a function that ignores its argument:

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

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

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

The fact that Option is monadic also means that we can apply to an Option[A] a function that takes an A and returns an Option[B] and get an Option[B]. For this example I'll use a function that attempts to parse a string into an integer:

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 上的那些.它还有一堆令人困惑的操作符(我之前已经吐槽过),包括你提到的那些,以及这些运算符只是 mapflatMap 的别名:

This is all relevant to your question because Parser is also monadic, and it has map and flatMap methods that work in very similar ways to the ones on Option. It also has a bunch of confusing operators (which I've ranted about before), including the ones you mention, and these operators are just aliases for map and flatMap:

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

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

So for example you could write the following:

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 示例中的一个相同.

Where each parser behaves in a way that's equivalent to one of the Option examples above.

这篇关于何时使用 scala 三重插入符 (^^^) 与双重插入符 (^^) 和 into 方法 (>>)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆