# Treat undef in Perl's <=> operator as +inf instead of 0

I have to sort some numbers with Perl. But some of the numbers are undefined. Perl's compare operator <=> treats undef as -inf 0. The result is, that the undefined numbers are at the beginning:

perl -MData::Dumper -e 'print Dumper(sort {$a <=>$b} 3, undef, 2, 1);'
$VAR1 = undef;$VAR2 = 1;
$VAR3 = 2;$VAR4 = 3;


I want them to occur at the end, because they represent new items, which should be added at the end. This means I am looking for a way to change the way Perl treats undef. In my case undef should be treated as +inf instead of -inf 0. I came up with the following expression.

($a <=>$b) * ((defined $a)*2-1) * ((defined$b)*2-1)


Is it always correct or did I miss anything?

And is there an easier way to achieve the same?

In fact, Perl treats undef as 0 in numeric contexts, and warns about that (why there's no -w in your one-liner?). You can use the defined-or operator to handle it:

sort { ($a // 'Inf') <=> ($b // 'Inf') } 3, undef, 2, 1


You need Perl v5.10+ for it to work, in older versions, you have to be more verbose:

(defined $a ?$a : 'Inf')

• I have Perl 5.8.4 here and using defined in the conditional operator has no effect on the sort order. Perl seems to understand 'Inf' but treats it as zero: pastebin.com/VAAP4dMw – ceving Oct 7 '15 at 15:16
• @ceving: You must have mis-coded it. It should look like sort { ( defined $a ?$a : 'Inf' ) <=> ( defined $b ?$b : 'Inf' ) } 3, undef, 2, 1 – Borodin Nov 29 '15 at 22:17

$a <=>$b will warn under warnings when one or both of variables is undef.

Thus, you can use short circuiting with || (high precedence OR operator), which will compare them only when both variables are defined (first two expressions evaluate to false),

sort { !defined($a)*1 || !defined($b)*-1 || $a <=>$b }


output

$VAR1 = 1;$VAR2 = 2;
$VAR3 = 3;$VAR4 = undef;

• I think the result must be 0, if both are undefined. – ceving Oct 8 '15 at 7:30
• @ceving you can my ($da,$db) = map {defined} $a,$b; ($da ||$db)*1 && (!$da*1 || !$db)*-1 || $a <=>$b) for correctness, but sort result will not change. – mpapec Oct 8 '15 at 7:59