http://www.perlmonks.org?node_id=999812


in reply to Multiple Sort on selected column

I happen to like to write separate subroutines for sorting, especially if I am going to do several different sorts that are need to be identical ... in that case, it’s only one thing to maintain and nothing to keep in-sync.

Multi-field comparison functions are made very easy by the <=> operator, (edit, see below) and ‘cmp’, both of which (as per perldoc perlop), “returns -1, 0, or 1 depending on whether the left argument is numerically or string-wise less than, equal to, or greater than the right argument.”   Combine this either of these with ||, which “performs a short-circuit logical-OR operation.   (“Short-circuit,” in the case of logical-OR, mans that if the left-hand part is determined to be “True,” evaluation of the right-hand part is omitted since “True OR anything == True.”)   Since any non-zero value is True, a series of <=> comparisons can be chained using || to produce the intended result.   It is clear at a glance what the code is doing.

{ $$a{'last_name'} cmp $$b{'last_name'} || $$a{'first_name'} cmp $$b{'first_name'} // evaluated only if 'last_ +name's are equal }

Very Important Edit!   It has very graciously been pointed out to me that the <=> operator is numeric whereas the cmp operator is the string operator that, in the foregoing example, I of course should have used.   (The above example has been edited to include it.)   One of the serious “gotchas” of Perl, which I confess that I have never quite understood, is that there are two entirely-separate sets of comparison and relational operators:   one for strings, and another for non-strings.   The original code, which used the <=> operator, would have compiled and ran, but would not have produced the intended result.   Thank-you to whoever-it-was for pointing this error out to me.   It is a critical error indeed.   But, with the change as noted, the original premise once again holds.   (We can defer the question of “why does Perl do this” ... indefinitely.)