自从开始看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呢?