14

文字のリストから、頻度にマップされた一意の文字のリストを生成しようとしています-たとえば、次のようなものです。

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

しかし、最後の 2 行を結合するだけで短くなるわけではありませんか?

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

「パラメータータイプがありません」というエラーが発生します。

Scala がこの構文について不平を言う理由を誰か説明できますか?

4

2 に答える 2

24

val s = l.toSetコンパイラが唯一の適切な型であるtoSetと言うとき、それCharが最も具体的な選択です。次に、sが のセットであるとするCharと、コンパイラはマップが からのものでなければならないことを認識しますChar

しかし、2 番目のケースでは、要素の型が何であるかについての判断を差し控えtoSetます。かもしれませんがCharAnyVal同様に機能し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-29T21:45:49.813 に答える
3

タイプ[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))
于 2012-10-29T21:39:29.913 に答える