Reputation: 3597
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
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
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