4

Trying to grok this comment, I wrote the following code:

def breakfast : AnyRef = {

    class Chicken  (e: =>Egg) { 
      lazy val offspring = e 
    }

    class Egg (c: =>Chicken) {
      lazy val mother = c
    }
   lazy val (egg: Egg, chicken: Chicken) = (new Egg(chicken), 
new Chicken(egg))
  egg  
}

And it works and it does exactly what you'd hope it'd do. What I don't get is, why is the : AnyRef necessary? If it's not included, the compiler (the 2.8 compiler at least) dies a horrible death:

error: type mismatch; found : Egg(in lazy value scala_repl_value) where type Egg(in lazy value scala_repl_value) <: java.lang.Object with ScalaObject{lazy def mother: Chicken} required: (some other)Egg(in lazy value scala_repl_value) forSome { type (some other)Egg(in lazy value scala_repl_value) <: java.lang.Object with ScalaObject{lazy def mother: Chicken}; type Chicken <: java.lang.Object with ScalaObject{lazy def offspring: (some other)Egg(in lazy value scala_repl_value)} } object RequestResult$line16$object {

Can somebody explain what's going on here?

Community
  • 1
  • 1
Michael Lorton
  • 43,060
  • 26
  • 103
  • 144

1 Answers1

4

You define classes Chicken and Egg in scope of breakfast function, so they are not seen outside i.e. nobody except breakfast don't know these classes. In Scala 2.9 this snippet actually works, and breakfast function's return value is defined as

def breakfast: Egg forSome { type Egg <: java.lang.object with scalaobject{lazy val mother: chicken}; type chicken <

When classes defined outside of function everything works as expected

class Chicken(e: => Egg) {
  lazy val offspring = e
}

class Egg(c: => Chicken) {
  lazy val mother = c
}

def breakfast: Egg = {

  lazy val (egg: Egg, chicken: Chicken) =
    (new Egg(chicken), new Chicken(egg))

  egg
}
dave4420
  • 46,404
  • 6
  • 118
  • 152
4e6
  • 10,696
  • 4
  • 52
  • 62
  • 1
    Right, but I think this is a compiler bug in 2.8. – Kipton Barros Sep 22 '11 at 06:22
  • I'm with you @KiptonBarros. The simplest case, `def a = { class Local; new Local }`, works; the next simplest case, `def a = { class Local; return new Local }`, which I think should be exactly equivalent, does not. – Michael Lorton Sep 22 '11 at 08:07
  • @Malvolio. The missing type inference in combination with a return type is not a bug, see this question for more info: [Type Inference on Method Return Type](http://stackoverflow.com/questions/2209179/type-inference-on-method-return-type) – kiritsuku Sep 22 '11 at 09:14
  • @Antoras, I see. Although in the particular case (the last line is the return statement) it wouldn't be difficult to infer the case, the general case (returns from anywhere) would be, plus the particular case is useless (the `return` keyword doesn't help you), so they decided to let it go. Still, I don't grasp why the `egg` type isn't understood as an `AnyRef` automatically. – Michael Lorton Sep 22 '11 at 10:51