【发布时间】:2018-09-23 19:07:39
【问题描述】:
在阅读 Chiusano 和 Bjarnason 的Scala 中的函数式编程时,我在第 9 章,解析器组合器中遇到了以下代码:
trait Parsers[ParseError, Parser[+_]] { self =>
...
def or[A](s1: Parser[A], s2: Parser[A]): Parser[A]
implicit def string(s: String): Parser[String]
implicit def operators[A](p: Parser[A]) = ParserOps[A](p)
implicit def asStringParser[A](a: A)(implicit f: A => Parser[String]):
ParserOps[String] = ParserOps(f(a))
case class ParserOps[A](p: Parser[A]) {
def |[B>:A](p2: Parser[B]): Parser[B] = self.or(p,p2)
def or[B>:A](p2: => Parser[B]): Parser[B] = self.or(p,p2)
}
}
我了解,如果在编译过程中出现类型不兼容或缺少参数,Scala 编译器会查找将不匹配类型转换为所需类型的缺失函数或范围内具有适合所需类型的变量分别缺少参数。
如果字符串出现在需要Parser[String]的地方,则应调用上述特征中的字符串函数将字符串转换为Parser[String]。
但是,我很难理解 operators 和 asStringParser 函数。这些是我的问题:
- 对于隐式运算符函数,为什么没有返回类型?
- 为什么 ParserOps 被定义为
case class以及为什么不能在 Parsers trait 本身中定义|或or函数? -
asStringParser究竟想要完成什么?它在这里的目的是什么? - 为什么需要
self?这本书说,“使用 self 明确消除对 trait 上的 or 方法的引用”,但这是什么意思?
我真的很喜欢这本书,但是本章中高级语言特定结构的使用阻碍了我的进步。如果你能向我解释这段代码是如何工作的,那将会很有帮助。我知道目标是通过| 和or 等运算符使库“更好”地使用,但不明白这是如何完成的。
【问题讨论】:
-
1) 它被称为 类型推断,是 1973 年以后发明的几乎所有编程语言的基本特征。 4) 因为你想在 @987654334 中调用
or@,不是ParserOps中的那个。
标签: scala parsing functional-programming implicit case-class