【问题标题】:Missing parameter type error by calling toSet?调用toSet时缺少参数类型错误?
【发布时间】:2012-10-19 06:17:54
【问题描述】:

尝试从字符列表中生成映射到其频率的唯一字符列表 - 例如类似:

List('a','b','a') -> List(('a',2), ('b',1))

所以,只是在控制台中乱搞,这行得通:

val l = List('a', 'b', 'c', 'b', 'c', 'a')       
val s = l.toSet                                  
s.map(i => (i, l.filter(x => x == i).size))

但是,仅通过合并最后两行来缩短不是吗?

l.toSet.map(i => (i, l.filter(x => x == i).size)) 

给出错误“缺少参数类型”。

谁能解释一下为什么 Scala 抱怨这种语法?

【问题讨论】:

  • 仅供参考,您可以使用myList.groupBy(identity).mapValues(_.size) 来完成您发布的第一件事。

标签: scala type-inference


【解决方案1】:

将类型 [Char] 添加到 toSet 就可以了。

scala> l.toSet[Char].map(i => (i, l.filter(x => x == i).size))
scala.collection.immutable.Set[(Char, Int)] = Set((a,2), (b,2), (c,2))

【讨论】:

  • 谢谢,虽然这会将问题推向“为什么”,因为我在第一个示例中没有提供该类型信息。
  • 查看 Rex 对“为什么”部分的回答。
【解决方案2】:

当您说val s = l.toSet 时,编译器认为toSet 的唯一合理类型是Char——这是最具体的选择。然后,假设s 是一组Char,编译器意识到映射必须来自Char

但在第二种情况下,它拒绝判断toSet 中的元素类型是什么。可能是Char,但AnyVal 也可以,Any 也可以。

l.toSet.map((i: Any) => (i, l.filter(x => x == i).size))

通常规则是编译器应该选择最具体的值。但是由于函数的参数是逆变的,所以当它们将Any 作为参数时,它们是最具体的,因此编译器无法决定。可能存在打破平局的规则(“更喜欢早期假设”),但没有实施。所以它需要你的帮助。

您可以在函数参数或toSet 上提供类型来解决问题:

l.toSet.map((i: Char) => (i, l.filter(x => x == i).size))
l.toSet[Char].map(i => (i, l.filter(x => x == i).size))

【讨论】:

    猜你喜欢
    • 2012-10-17
    • 2018-03-28
    • 2012-02-23
    • 2017-03-18
    • 2021-04-22
    • 2017-08-20
    • 1970-01-01
    • 2014-02-08
    • 1970-01-01
    相关资源
    最近更新 更多