Reputation: 11
I'm using Scala 2.9
I have a class:
class Queue[T] private( private val heading: List[T], private val trailing: List[T] ) {
def this( a: T* ) = this( a.toList, Nil )
private def mirror = {
if ( heading.isEmpty ) {
new Queue[T]( trailing.reverse, Nil )
} else this
}
def head = {
val q = mirror
if ( q.heading.isEmpty ) None else new Some(q.heading.head)
}
def tail = {
val q = mirror
if ( q.heading.isEmpty ) q else new Queue[T]( q.heading.tail, trailing )
}
def enqueue( a: T ) = {
new Queue[T]( heading, a::trailing )
}
}
In method enqueue, if I write new Queue( heading, a::trailing )
(leaving out the type parameter [T]), the code won't compile and scalac complaints about "ambiguous reference to overloaded definition, both constructor Queue in class Queue of type (a: T*)Queue[T] and constructor Queue in class Queue of type (heading: List[T], trailing: List[T])Queue[T] match argument types (List[T],List[T])".
So why is it necessary to explicitly specify the type parameter[T]
otherwise Scala will treat the two separate Lists as a whole for a repeat parameter? I think it has something to do with type inference, could someone please explain it?
Upvotes: 1
Views: 395
Reputation: 24403
Heiko's answer is correct, but to clarify this a bit, the T
in enqueue
is a different T
than the one in the context of the Queue
you are about to create and has therefore to be inferred which leads to the ambiguity. Why do you have 2 constructors anyway? I would suggest you to use a companion for your constructor for the outer world:
class Queue[T] private( private val heading: List[T], private val trailing: List[T]) { /* ... */}
object Queue {
def apply[T](xs: T*) = new Queue(xs.toList, Nil)
}
Upvotes: 2
Reputation: 3722
If you don't give the type argument, the compiler could either infer T
(for the primary constructor) or List[T]
(for the auxiliary constructor).
Upvotes: 2