PfSensePuzzled PfSensePuzzled - 4 months ago 17
Scala Question

Partial Function values for sorting

I want to sort a list dependent on an external predicate. I'm looking for alternatives in Scala that are expressive. I'm not crazy about the two alternatives I've come up with. Given:

val lst = List(5,4,3,2,1)
val needsSorting = false


I want to be able to write a concise sort expression like so:

lst.sortBy(sortDecision)


to give me the list sorted either in ascending order:

List(1,2,3,4,5) // if needSorting == true


or in the original chronological order

List(5,4,3,2,1) // if needSorting == false


BUT I want the decision on HOW to sort to be embedded in my
sortDecision
partial function. What I've come up with are two alternatives:

Alternative 1:

val sortDecision: PartialFunction[Int,Int] = {
case x: Int if (needsSorting) => x
case _ => -1
}


Alternative 2:

val sortDecision: PartialFunction[Int,Int] = {
case x: Int => if (needsSorting) x else -1
}


but in both cases I have the !needsSorting case having to produce some filler (in this case -1) for the compiler to be happy. This is bad code smell. Can anyone offer an alternative to accomplish the same thing that is a bit more elegant?

Answer

I think that the more elegant way is to not sort at all if needsSorting == false because I think it is the only way that your intent will be completely clear.

Another way to achieve this would be to supply an Ordering but you'd end up having to do something similar there (such as comparing dummy values) if you want to make the decision within the Ordering.

You might already know that the reason that returning -1 leaves the list unsorted is that sortBy transforms each Int into another value and then uses that value when comparing. So in your example it's like sorting List(-1,-1,-1,-1,-1) and then putting back the original values. Because scala sort is stable this leaves all the elements in the same order.