digizer0
digizer0

Reputation: 11

Scala repeated parameters and parameters in List confusion

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

Answers (2)

drexin
drexin

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

Heiko Seeberger
Heiko Seeberger

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

Related Questions