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?
The Scala compiler can infer the types of expressions automatically from contextual information. Therefore, we need not declare the types explicitly. This feature is commonly referred to as type inference. It helps reduce the verbosity of our code, making it more concise and readable.
In Scala there are two types of variables: Mutable Variables. Immutable Variables.
Type inference is the ability to automatically deduce, either partially or fully, the type of an expression at compile time. The compiler is often able to infer the type of a variable or the type signature of a function, without explicit type annotations having been given.
Methods in Scala can be parameterized by type as well as by value. The syntax is similar to that of generic classes. Type parameters are enclosed in square brackets, while value parameters are enclosed in parentheses.
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
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With