简体   繁体   中英

Scala sortBy Missing parameter type for expanded function

I have created a list of lists like this and I can sort this easily on size.

@ List(List(2, 2, 3), List(7)).sortBy(_.size)
res71: List[List[Int]] = List(List(7), List(2, 2, 3))

However If I have list which has duplicates and I want to eliminate the duplicates I can do

@ List(List(2, 2, 3), List(3, 2, 2), List(7)).map(_.sorted).toSet.toList
res72: List[List[Int]] = List(List(2, 2, 3), List(7))

You can see the data type of the list above is still List[List[Int]]

Now If I try

@ List(List(2, 2, 3), List(3, 2, 2), List(7)).map(_.sorted).toSet.toList.sortBy(_.size)
cmd73.sc:1: missing parameter type for expanded function ((x$2: <error>) => x$2.size)
val res73 = List(List(2, 2, 3), List(3, 2, 2), List(7)).map(_.sorted).toSet.toList.sortBy(_.size)
                                                                                          ^
Compilation Failed

I also tried

@ List(List(2, 2, 3), List(3, 2, 2), List(7)).map(_.sorted).toSet.toList.sortBy(x => x.size)
cmd73.sc:1: missing parameter type
val res73 = List(List(2, 2, 3), List(3, 2, 2), List(7)).map(_.sorted).toSet.toList.sortBy(x => x.size)
                                                                                          ^
Compilation Failed

I am a little confused. What is the difference between the List[List[Int]] which I build manually vs List[List[Int]] which comes back from the toList function? why is it that I can call sortBy on the first one, but I can't call sortBy on the second one?

In above example, .toSet is loosing elements type for List[T] ,

def toSet[B >: A]: immutable.Set[B] = to[immutable.Set].asInstanceOf[immutable.Set[B]]

scala> List(List(2, 2, 3), List(3, 2, 2), List(7)).map(_.sorted).toSet.foreach(x => println(x))
<console>:12: error: missing parameter type
       List(List(2, 2, 3), List(3, 2, 2), List(7)).map(_.sorted).toSet.foreach(x => println(x))
                                                                           ^

But you can verify that it gives right type for simple types T ,

scala> List(1, 2, 3, 4, 5, 4, 3, 2, 1).toSet.toList.sorted
res0: List[Int] = List(1, 2, 3, 4, 5)

So, only specifying a type for List[T] is working.

scala> List(List(2, 2, 3), List(3, 2, 2), List(7)).map(_.sorted).toSet.foreach((x: List[Int]) => println(x))
List(2, 2, 3)
List(7)

//set type to toSet
scala> List(List(2, 2, 3), List(3, 2, 2), List(7)).map(_.sorted).toSet[List[Int]].foreach(x => println(x))
List(2, 2, 3)
List(7)

To make your example work give either toSet (see another answer as well ) or elem a type while processing the elem.

scala> List(List(2, 2, 3), List(3, 2, 2), List(7)).map(_.sorted).toSet.toList.sortBy((x: List[Int]) => x.size)
res2: List[List[Int]] = List(List(7), List(2, 2, 3))

And also, you can use .distinct instead of .toSet

scala> List(List(2, 2, 3), List(3, 2, 2), List(7)).map(_.sorted).distinct.sortBy(_.size)
res3: List[List[Int]] = List(List(7), List(2, 2, 3))

The problem comes from the definition of toSet :

def toSet[B >: A]: Set[B]

As you can see, there is a type parameter to be inferred. Scala can still infer this in your first example with toSet , but the one involving a lambda has more complicated type inference that Scala apparently can't handle. You can fix this by providing the parameter type for your lambda or, more simply, the type parameter to toSet :

List(List(2, 2, 3), List(3, 2, 2), List(7)).map(_.sorted).toSet[List[Int]].toList
    .sortBy(_.size)

As prayagupd points out , you can also use .distinct .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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