laiboonh
laiboonh

Reputation: 1457

How to resolve self reference in this case?

For the two blocks of code, i expected the self reference in both blocks to be Foo[A]. However it seems the second block does not compile. Can someone explain to me how to resolve the self references?

trait Foo[A] {
  def format(value:A):String
  def bar[B](f:B=>A):Foo[B] = {
    val self = this
    new Foo[B] {
      override def format(value: B): String = self.format(f(value))
    }
  }
}

trait Foo[A] {
  def format(value:A):String
  val self = this
  def bar[B](f:B=>A):Foo[B] = {      
    new Foo[B] {
      override def format(value: B): String = self.format(f(value))
    }
  }
}

Upvotes: 1

Views: 69

Answers (1)

stefanobaghino
stefanobaghino

Reputation: 12804

self get assigned this, which is a reference to a particular instance, the one you're calling a method (or a constructor) at invocation.

In the first snippet, you invoke the method bar on an object of type Foo[A], meaning that at that point this means the instance of Foo[A]. After you assign this to self you proceed to create a new instance of Foo, this time giving the type parameter a different type, but self.

In the second snippet you are saying that objects of type Foo[A] have a member field that is called self and gets assigned this. This will apply to all instances of Foo[_], regardless of how you call the type parameter. When you create a second Foo calling the type parameter B, this second instance will nonetheless have a member field self, which gets assigned this, which at this point is Foo[B] and shades the self that you declared as part of the initial declaration of Foo.

This means that in the second snippet, you the format method implementation of Foo[B] has access to a self reference of Foo[B] itself, which causes the type error you mentioned.

  • Foo[B] has method format(value: B)
  • method bar takes a function that takes a B and transforms it into an A
  • You apply f: B => A to value: B, turning it into an A, then you try to feed A to Foo[B]#format(value: B)

Sorry for the convoluted response; in short: type parameters are mere placeholder names for actual types just like value parameters are placeholder names for actual runtime values. Apply the same reasoning to both types and values and reasoning about them will become easier.

Upvotes: 2

Related Questions