Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

I don't know what you mean by "sorting key" in this context. The idiom I have in mind is how .Net implements "SortBy", "ThenBy" and friends. Overloads can be used for a comparator function based approach, but it should not be the first choice.

And I'll stand by comparators being easy to get wrong, particularly when values may be null, polymorphic, etc.



> I don't know what you mean by "sorting key" in this context.

The result of the projection which is associated with each value and used to actually sort the values.

> The idiom I have in mind is how .Net implements "SortBy", "ThenBy" and friends.

I assume you mean OrderBy. I see, instead of having sorting as a single atomic operation it becomes a stateful multi-step transformation of the iterator. I can still see weirdness in it: what are the constraints on the return value of the key selector functions? The MSDN does not list any, but that can't be right: what if the key selector returns a value which can not be sorted itself?

> And I'll stand by comparators being easy to get wrong, particularly when values may be null, polymorphic, etc.

Trivial key extraction does not make that any easier: instead of being hard, hard cases become impossible.


> > And I'll stand by comparators being easy to get wrong, particularly when values may be null, polymorphic, etc.

> Trivial key extraction does not make that any easier: instead of being hard, hard cases become impossible.

Perhaps you missed this bit:

> > Overloads can be used for a comparator function based approach, but it should not be the first choice.

Key extraction makes trivial cases less error prone than comparators; overloads can be used to make the hard cases possible. Comparators everywhere make all cases error-prone.


For the record, T needs to implement IComparable<T>. I think there are special rules for anonymous types for convenience.

And do bear in mind that C# supports both idioms. So you can handle hard cases any way you want.


>I don't know what you mean by "sorting key" in this context.

He means the item by which you sort. The "by" in your "SortBy" example.


Yes, but that reading doesn't make sense given what he also wrote - that apparently this would make things more awkward in a static language.


How do you define the sorting key in a static language? With reflection?

e.g if anArray is a Java array of Employee objects, and you want to sort on their salary attribute, how do you specify it?

anArray.sortBy(???);

In a dynamic language it doesn't matter much, since all attribute access amounts to (and is as slow as) reflection on a static language anyway, so you can do something like, say:

anArray.sortBy("salary");


In Haskell, sortBy takes a comparison function:

  sortBy :: (a -> a -> Ordering) -> [a] -> [a]
And Ordering is defined as:

  data Ordering = LT | EQ | GT
If you want to provide a "key" function rather than a comparison function, you can use sortOn:

  sortOn :: Ord b => (a -> b) -> [a] -> [a]
Which is basically just a sortBy with a function that applies the key function and then compares as normal.


And everything is statically typed.


In JDK8 there are method references that could enable this. For example, you can reference a method in a class like Person::age ( equivalent to (Person person) -> person.age() ) that could then be used to sort the collection since Integer implements Comparable.


AnArray.Sort(e -> e.Salary) and if there's no built-in way to compare two Salary objects (let's say they're complex objects), then you come up with an interface that the sorting function would use and the objects would implement. This way you let the objects compare themselves.




Consider applying for YC's Fall 2026 batch! Applications are open till July 27.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: