Question

I don't think there's any difference, or reason to prefer one over the other, but wanted to check...

def length(l: List[Any])
def length[T](l: List[T])
Was it helpful?

Solution 2

If you just want the length of any List, there is no difference for you.
But if you want operatations with the elements of that list, there is.

val l = List(1, 2, 3, 4)
def secondElementAny(l: List[Any]) = l.tail.head
def secondElementGen[A](l : List[A]) = l.tail.head

Giving those two functions and the list, we will expect to get the 2 from the List.

val secondAny = secondElementAny(l)
val secondGen = secondElementGen(l)

If we would print the values to the console, we could spot no diference, but if we try to cast them to Float for example, we will get an error. secondAny.toFloat will tell us, that secondAny is type of Any and that we cannot use the function toFloat on Any.
In contrast secondGen.toFloat will give us a Float value.

The reason for that is, that the compiler aproximates the full signatures as follows.

def secondElementAny(l: List[Any]): Any = l.tail.head
def secondElementGen[A](l: List[A]): A = l.tail.head

As you can see the return type of the first function is Any, so we will always get an Any whereas the return type of the second function depends on the type of the List. We will get an element of that type. This is typesafe.

OTHER TIPS

You could also write it like this:

def length(l: List[_])

Now, with regards to your question, List[Any] will, indeed accept any List, but if you had tried Set[Any], it would not work! For instance, try passing a Set[Int] to it:

scala> def length(s: Set[Any]) = s.size
length: (s: Set[Any])Int

scala> val set = Set(1, 2, 3)
set: scala.collection.immutable.Set[Int] = Set(1, 2, 3)

scala> length(set)
<console>:10: error: type mismatch;
 found   : scala.collection.immutable.Set[Int]
 required: Set[Any]
Note: Int <: Any, but trait Set is invariant in type A.
You may wish to investigate a wildcard type such as `_ <: Any`. (SLS 3.2.10)
              length(set)
                     ^

List is co-variant, which makes that possible, but not every parameterized class is covariant. Either your parameterized version or the version above will work, though.

I can't think of any reason to prefer one over the other, but I'd rather not parameterize something when it is not needed. If nothing else, it will have a slight positive impact on compilation speed.

There is a difference:

def head_1(l: List[Any]) = {
  l.head
}

def head_2[T](l: List[T]) = {
  l.head
}

// Doesn't compile, head_1 returns Any
// head_1(List(1,2,3)) > 1

head_2(List(1,2,3)) > 1                   //> res0: Boolean = false
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top