为什么这个“别名”在Scala中起作用?

8 浏览
0 Comments

为什么这个“别名”在Scala中起作用?

在Coursera课程“响应式编程原理”中,Odersky介绍了以下代码片段:

trait Generator[+T] {
    self => // “this”的别名。
    def generate: T
    def map[S](f: T => S): Generator[S] = new Generator[S] {
        def generate = f(self.generate)
    }
    def flatMap[S](f: T => Generator[S]): Generator[S] = new Generator[S] {
       def generate = f(self.generate).generate
    }
}

然而,我对self =>这个东西不太熟悉。为什么它可以工作,为什么我不能只是用val self = this

0
0 Comments

在Scala中,为什么这个“别名”在代码中起作用?

在Scala中,有一个问题需要解决,即在map和flatMap方法中,需要从新创建的内部Generator中引用外部的Generator。如果在代码中使用this代替self,就无法识别外部Generator,而是识别内部的Generator。因为this始终指的是离使用它的位置最近的类实例。

为了解决这个问题,可以添加一个self方法来引用外部的Generator。但是在内部作用域中,新创建的Generator会有自己的self方法,从而再次调用了错误的self方法。

相比之下,别名并不是一个方法,在代码示例中并不存在“两次”,因此当你写下new Generator时,并不存在遮蔽的情况。这只是一个更简洁的方式,用于捕获外部实例并在内部引用它。

解决方法是在map方法中添加一个内部变量outer来捕获外部实例,然后在内部引用outer实例来调用generate方法。下面是代码示例:

def map[S](f: T => S): Generator[S] = {
  val outer = this  // capture outer instance, since `this` will change meaning
  new Generator[S] {
    def generate = f(outer.generate)  // refer to the outer instance
  }
}

通过这种方式,我们可以正确引用外部的Generator,解决了问题。

0