knuton
knuton

Reputation: 3597

Different type inference for `def` and `val` in Scala

I observed a difference in Scala's type inference when applied to def and val.

Using def, I can define an abstract nullary method const returning some value of type Int => Int. When implementing const with a function literal, I need not supply a parameter type, as it can be inferred by the compiler:

trait D {
  def const: Int => Int
}
object D extends D {
  def const = i => i + 1
}

This is fine. (On the downside, a new function instance is being created for every access to D.const.)

Now consider an analogous construction using val:

trait V {
  val const: Int => Int
}
object V extends V {
  val const = i => i + 1
}

This will not compile, failing with

error: missing parameter type
   val const = i => i + 1
               ^

Why?

Upvotes: 18

Views: 501

Answers (2)

knuton
knuton

Reputation: 3597

As of Scala 2.9.1, this is “as speced”. Citing Martin Odersky from SI-2742:

For methods, return types in inherited abstract methods are taken as expected type of the right hand side. For values there is no such rule. So this would be a spec enhancement request, as I see it.

The ticket is low priority and has remained unchanged since its first discussion in late 2009, so it seems unlikely to change anytime soon.

Upvotes: 1

fp4me
fp4me

Reputation: 463

If you build this code with the option -Xprint all , you will see that :

abstract trait V extends scala.AnyRef {   
<stable> <accessor> def const: Int => Int
};

final object V extends java.lang.Object with V with ScalaObject {

def this(): object V = {
  V.super.this();
  ()
};

private[this] val const: <error> => <error> = ((i: <error>) => i.+(1));
<stable> <accessor> def const: <error> => <error> = V.this.const
}

So the error occurs at the creation of private val and accessor. th compilator try to evaluate the value affected to the val const before creating the accessor def const.

if you look to the val const defined in trait, you see that the creation of private val was disabled because it's only a definition for the def const accessor.

I think the inference type with previous definition ( in trait or superclass) occurred only when he try to create the accessor, not for evaluate a value.

And for the last def const , the type is only based on the private[this] val const type : error => error

Upvotes: 2

Related Questions