首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >理解Scala Implicits

理解Scala Implicits
EN

Stack Overflow用户
提问于 2018-04-13 12:12:25
回答 1查看 152关注 0票数 2

在阅读Chiusano和Bjarnason在Scala中的函数式编程时,我在第9章Parser Combinator中遇到了以下代码:

代码语言:javascript
复制
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]的位置,则应调用上述特性中的string函数将字符串转换为Parser[String]

但是,我很难理解operatorsasStringParser函数。以下是我要问的问题:

  1. 对于隐式运算符函数,为什么没有返回类型?
  2. 为什么ParserOps被定义为case class,为什么不能在解析器特征本身中定义|or函数?
  3. asStringParser到底想要达到什么目的?它在这里的目的是什么?
  4. 为什么需要self?这本书说,“使用自我来明确地消除对特征的或方法的引用”,但这意味着什么呢?

我真的很喜欢这本书,但是在本章中使用高级语言结构阻碍了我的进步。如果您能向我解释这段代码是如何工作的,这将有很大的帮助。我知道目标是通过|or这样的运算符来使库“更好”使用,但不明白这是如何做到的。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-04-13 15:15:02

  1. 每个方法都有一个返回类型。在这种情况下,它是ParserOps[A]。您不必显式地写出它,因为在这种情况下,可以自动推断它。
  2. 可能是因为同伴对象中自动提供了ParserOps.apply-factory方法。构造函数中需要更少的val,并且不需要new关键字来实例化ParserOps。但是,它并不用于模式匹配,因此,您可以使用一个普通的(非case)类做同样的事情,这并不重要。
  3. 这是“皮条客-我的图书馆”-pattern。它将方法|or附加到Parser,而不强制Parser继承任何东西。这样,以后可以声明Parser是类似于ParserState => Result[A]的东西,但是仍然有|or可用的方法(尽管Function1[ParserState, Result[A]]没有它们)。
  4. 您可以将|or直接放在Parsers中,但是必须使用以下语法 (a,b)或(a,b) 而不是更好的 A、b、a或b

Scala中没有“真正的运算符”,一切都是一种方法。如果您想要实现一个行为像infix操作符一样行为的方法,那么您可以做书中所做的事情。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/49816716

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档