简体   繁体   English

调用toSet丢失参数类型错误

[英]missing parameter type error by calling toSet

Why this code doesn't work: 为什么这段代码不起作用:

scala> List('a', 'b', 'c').toSet.subsets.foreach(e => println(e))

<console>:8: error: missing parameter type
              List('a', 'b', 'c').toSet.subsets.foreach(e => println(e))
                                                        ^

But when I split it then it works fine: 但是当我拆分它然后它工作正常:

scala> val itr=List('a', 'b', 'c').toSet.subsets
itr: Iterator[scala.collection.immutable.Set[Char]] = non-empty iterator

scala> itr.foreach(e => println(e))
Set()
Set(a)
Set(b)
Set(c)
Set(a, b)
Set(a, c)
Set(b, c)
Set(a, b, c)

And this code is OK as well: 这段代码也可以:

Set('a', 'b', 'c').subsets.foreach(e => println(e))

First, there's a simpler version of the code that has the same issue: 首先,有一个更简单的代码版本具有相同的问题:

List('a', 'b', 'c').toSet.foreach(e => println(e))

This doesn't work either 这也不起作用

List('a', 'b', 'c').toBuffer.foreach(e => println(e))

However, these work just fine: 但是,这些工作正常:

List('a', 'b', 'c').toList.foreach(e => println(e))
List('a', 'b', 'c').toSeq.foreach(e => println(e))
List('a', 'b', 'c').toArray.foreach(e => println(e))

If you go take a look at the List class documentation you'll see that the methods that work return some type parameterized with A , whereas methods that don't work return types parameterized with B >: A . 如果你去看一下List类文档,你会看到有效的方法返回一些用A参数化的类型,而不起作用的方法返回用B >: A参数化的类型B >: A The problem is that the Scala compiler can't figure out which B to use! 问题是Scala编译器无法确定使用哪个B That means it will work if you tell it the type: 这意味着如果你告诉它类型它会工作:

List('a', 'b', 'c').toSet[Char].foreach(e => println(e))

Now as for why toSet and toBuffer have that signature, I have no idea... 至于为什么 toSettoBuffer有这个签名,我不知道......

Lastly, not sure if this is helpful, but this works too: 最后,不确定这是否有用,但这也有效:

// I think this works because println can take type Any
List('a', 'b', 'c').toSet.foreach(println)

Update: After poking around the docs a little bit more I noticed that the method works on all the types with a covariant type parameter, but the ones with an invariant type parameter have the B >: A in the return type. 更新:在更多地讨论文档后,我注意到该方法适用于所有具有协变类型参数的类型,但具有不变类型参数B >: A在返回类型中具有B >: A Interestingly, although Array is invariant in Scala they provide two version of the method (one with A and one with B >: A ), which is why it doesn't have that error. 有趣的是,尽管Array在Scala中是不变的,但它们提供了两个版本的方法(一个带有A ,一个带有B >: A ),这就是为什么它没有这个错误。

I also never really answered why breaking the expression into two lines works. 我也从未真正回答为什么将表达式分成两行。 When you simply call toSet on its own, the compiler will automatically infer A as B in the type for the resulting Set[B] , unless you do give it a specific type to pick. 当你自己简单地调用toSet时,编译器会自动在结果Set[B]的类型中推断AB ,除非你给它一个特定的类型来选择。 This is just how the type inference algorithm works. 这就是类型推断算法的工作原理。 However, when you throw another unknown type into the mix (ie the type of e in your lambda) then the inference algorithm chokes and dies—it just can't handle an unknown B >: A and an unknown type of e as well. 但是,当你在混合中抛出另一种未知类型(即你的lambda中的e的类型)时,推理算法会扼杀和死亡 - 它只能处理未知的B >: A和未知类型的e

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM