自从开始看scala的Parser相关的源码以来,我越来越觉得scala中很多处理方法就像是用黑魔法在与编译器打交道。不变成JVM上的c++誓不罢休?
看Programming in Scala 源码 33.6
- abstract class Parser[+T] ... { p =>
- ...
- def ~ [U](q: => Parser[U]) = new Parser[T~U] {
- def apply(in: Input) = p(in) match {
- case Success(x, in1) =>
- q(in1) match {
- case Success(y, in2) => Success(new ~(x, y), in2)
- case failure => failure
- }
- case failure => failure
- }
- }
结果查2.9.1里的代码
- def ~ [U](q: => Parser[U]): Parser[~[T, U]] = { lazy val p = q // lazy argument
- (for(a <- this; b <- p) yield new ~(a,b)).named("~")
- }
named方法的定义
- def named(n: String): this.type = {name=n; this}
对这个地方一直不明白,查到了这篇文章 后才了解到它的作用。
class A {def method1: A = this } class B extends A (def method2: B = this} val b = new B
如果调用b.method2.method1是可以的,但是如果想调用b.method1.method2就不行了。因为method1返回的是A类型的。
当然你可以在B中覆盖method1,以返回正确类型。但是scala中解决这个问题的办法就是this.type
class A { def method1: this.type = this } class B extends A { def method2: this.type = this } val b = new B
如果调用b.method1则编译器会知道method1返回的是B类型的。
自言自语:
scala学习曲线过高,代码可读性差(也许我读得还不够多),大量的语法规则和复杂的类型申明让我头晕。是不是该继续尝试更为纯粹的clojure呢