为什么 Scala 在第一种情况下会警告类型擦除而不是第二种情况? [英] Why does Scala warn about type erasure in the first case but not the second?

查看:57
本文介绍了为什么 Scala 在第一种情况下会警告类型擦除而不是第二种情况?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两个函数(这些函数自原始以来没有被编辑过——下面的一些答案是对返回一系列 () 的原始答案的回应):

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 ()):

def foo1[A](ls: Iterable[A]) : Iterator[A] =
    for (List(a, b) <- ls sliding 2) yield a

def foo2[A](ls: Iterable[A]) : Iterator[A] =
    for (a::b::Nil <- ls sliding 2) yield a

我天真地认为是一样的.但是 Scala 只为第一个提供了这种减弱:

which I naively thought were the same. But Scala gives this waning only for the first one:

warning: non variable type-argument A in type pattern List[A]
is unchecked since it is eliminated by erasure

我想我明白为什么它会为第一个错误提供该错误:Scala 认为我正在尝试使用该类型作为模式的条件,即与 List[B](_, _) 如果 B 不从 A 继承,应该失败,除非这不会发生,因为在两种情况下类型都被擦除了.

I think I understand why it gives that error for the first one: Scala thinks that I'm trying to use the type as a condition on the pattern, ie a match against List[B](_, _) should fail if B does not inherit from A, except that this can't happen because the type is erased in both cases.

所以两个问题:

1) 为什么第二个没有给出同样的警告?

1) Why does the second one not give the same warning?

2) 是否可以让 Scala 相信该类型在编译时实际上是已知的,因此不可能不匹配?

2) Is it possible to convince Scala that the type is actually known at compile time, and thus can't possibly fail to match?

我认为这回答了我的第一个问题.但我还是对第二个很好奇.

edit: I think this answers my first question. But I'm still curious about the second one.

agilesteel 在评论中提到

edit: agilesteel mentioned in a comment that

for (List(a, b) <- List(1,2,3,4) sliding 2) yield ()

不产生警告.这与 foo1 有什么不同([Int] 参数不应该和 [A] 参数一样被删除)?

produces no warning. How is that different from foo1 (shouldn't the [Int] parameter be erased just the same as the [A] parameter is)?

推荐答案

我不确定这里发生了什么,但是 Iterable[A].sliding 的静态类型是 Iterator[Iterable[A]],而不是 Iterator[List[A]],后者是 List[A].sliding 的静态类型.

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.

您可以尝试接收 Seq 而不是 Iterable,这也行.EDIT 与我之前声称的相反,IterableSeq 都是协变的,所以我不知道有什么不同.END EDIT 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]]

看看它是如何需要一个 BA 的超类,但从未被使用过?对比一下 Iterator.sliding,它没有问题:

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

这里你对列表进行了两次分解,对于每次分解,head 的类型都会根据 A 进行检查.由于 head 的类型没有被擦除,所以你没有问题.这也主要是猜测.

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.

最后,如果你把ls变成一个List,你就不会有问题了.否则,我认为您无能为力.否则,你也可以这样写:

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

这篇关于为什么 Scala 在第一种情况下会警告类型擦除而不是第二种情况?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆