Why does Scala warn about type erasure in the first case but not the second?

前端 未结 3 899
耶瑟儿~ 2021-02-20 18:39

I have two functions (not these have been edited since the original -- some of the answers below are responding to the original ones which returned a sequence of ()):


  • 2021-02-20 18:55

    1) The second one does not produce a warning probably because you are constructing the list (or the pattern) by prepending elements to the Nil object, which extends List parameterising it with Nothing. And since everything is Nothing, there is nothing to be worried about ;) But I'm not sure, really guessing here.

    2) Why don't you just use:

    def foo[A](ls: Iterable[A]) =
        for (list <- ls sliding 2) yield ()
    0 讨论(0)
  • 2021-02-20 19:13

    I'm not sure what is happening here, but the static type of Iterable[A].sliding is Iterator[Iterable[A]], not Iterator[List[A]] which would be the static type of List[A].sliding.

    You can try receiving Seq instead of Iterable, and that work too. EDIT Contrary to what I previously claimed, both Iterable and Seq are co-variant, so I don't know what's different. END EDIT The definition of sliding is pretty weird too:

    def sliding [B >: A] (size: Int): Iterator[Iterable[A]]

    See how it requires a B, superclass of A, that never gets used? Contrast that with an Iterator.sliding, for which there's no problem:

    def sliding [B >: A] (size: Int, step: Int = 1): GroupedIterator[B]

    Anyway, on to the second case:

    for (a::b::Nil <- ls sliding 2) yield a

    Here you are decomposing the list twice, and for each decomposition the type of head is checked against A. Since the type of head is not erased, you don't have a problem. This is also mostly a guess.

    Finally, if you turn ls into a List, you won't have a problem. Short of that, I don't think there's anything you can do. Otherwise, you can also write this:

    def foo1[A](ls: Iterable[A]) : Iterator[A] =
        for (Seq(a, b) <- ls.iterator sliding 2) yield a
    0 讨论(0)
  • 2021-02-20 19:15

    I'm not really familiar with Scala, but I have used Java and Haskell, so I'm going to go out on a limb here and guess that your second example isn't doing quite the same thing. It looks like both of them are using a pattern match to deconstruct the first two elements of a list, but the second one is using the cons operator as opposed to the List constructor. My guess would be that this is somehow related to the interop with Java and a subtle difference between the way the List constructor versus the cons operator actually function.

    On the other hand, maybe it's just an edge case that got overlooked by the compiler and they both should generate a warning.

    0 讨论(0)