What's the difference between these two calls to a function taking a collection of structural types?
Why does the call to fn(Iterator("foo") compile, but the call to fn(fooIterator) fail with an error "type mismatch; found : I开发者_运维问答terator[java.lang.String] required: scala.Iterator[com.banshee.Qx.HasLength]"
object Qx {
type HasLength = {def length: Int}
def fn(xs: Iterator[HasLength]) = 3
var tn = fn(Iterator("foo"))
var fooIterator = Iterator("foo")
var tnFails = fn(fooIterator) //doesn't compile
}
Aren't they the same thing?
It has to be a bug in the representation of refinements, because the following two formulations both work.
object Qx1 {
// give length() parens, even though the Iterator definition doesn't have them
type HasLength = { def length(): Int }
def fn(xs: Iterator[HasLength]) = 3
var tn = fn(Iterator("foo"))
var fooIterator = Iterator("foo")
var tnFails = fn(fooIterator) //doesn't compile
}
object Qx2 {
type HasLength = { def length: Int }
def fn(xs: Iterator[HasLength]) = 3
var tn = fn(Iterator("foo"))
// annotate the type of fooIterator before the type inferencer can mis-infer
var fooIterator: Iterator[HasLength] = Iterator("foo")
var tnFails = fn(fooIterator) //doesn't compile
}
Edit:
Too early in the morning. It's String with the length() method, which does have parens, which means it's right and you're wrong for thinking length and length() are the same method. (It's a nice little trap I've documented before.)
This formulation works:
object Qx {
type HasLength = {def length: Int}
def fn[HL <% HasLength](xs: Iterator[HL]) = 3
val tn = fn(Iterator("foo"))
val fooIterator = Iterator("foo")
val tnFails = fn(fooIterator)
}
精彩评论