2010-07-09 36 views
7

que tiene esta pieza de la escritura:comportamiento extraño del tipo

#!/usr/bin/perl 
use strict; 
use warnings; 
use Data::Dumper; 

my @arr = (
    { 
     name => 'foo', 
     value => 123, 
    }, 
    { 
     name => 'bar', 
     value => 'nan', 
    }, 
    { 
     name => 'foobar', 
     value => 456, 
    }, 
); 

@arr = sort {$a->{value} <=> $b->{value} } @arr; 

print Dumper(\@arr); 

no tengo ningún problema en Windows XP/Strawberry Perl 5.10.1

ya sea Linux i386 2.6.12-1/Perl v5.8.5 construido para i386-linux-hilos múltiples,

pero bajo Linux 2.6.18-53/Perl v5.8.8 construido para x86_64-linux-hilos múltiples, que recibió el mensaje de error:

Sort subroutine didn't return a numeric value at testsort.pl line 21. 

¿Qué sucede y cómo puedo solucionarlo?

+0

¿Ocurre lo mismo si lo simplifica así? @arr = sort {$ a <=> $ b} (123, 'nan', 456); – wdebeaum

+0

@wdebeaum: no hay errores en un trazador de líneas, pero no ordena nada en x86_64, mientras que está bien en Windows XP y i386 – Toto

Respuesta

6

En algunas compilaciones, 'nan' se fuerza al número 0 para una comparación <=> y la ordenación tiene éxito. En otras compilaciones, nan se trata como "no es un número" y el valor de retorno desde <=> no está definido.

Para una máxima portabilidad, probar un valor para si se trata de un buen número de no:

(isnan subrutina de How do I create or test for NaN or infinity in Perl?):

sub isnan { ! defined($_[0] <=> 9**9**9) } 

@arr = sort { isnan($a->{value}) ? 0 : $a->{value} 
         <=> 
       isnan($b->{value}) ? 0 : $b->{value} } @arr; 
+0

Funciona. He rodeado ternario por paréntesis. – Toto

4

2 Soluciones

  1. mobrule La solución de:

    solución de 210
    sub isnan { ! defined($_[0] <=> 9**9**9) } 
    @arr = sort { isnan($a->{value}) ? 0 : $a->{value} 
               <=> 
           isnan($b->{value}) ? 0 : $b->{value} } @arr; 
    
  2. Perldoc 's:

    @result = sort { $a <=> $b } grep { $_ == $_ } @input; 
    

  1. Da a su NaN un valor 0, que debe empujar a la parte superior de la lista.
  2. Aprovecha que NaN != NaN, para eliminar cualquier NaN s de la lista de entrada.

Como mobrule indicó, esto se debe a la comparación de NaN entre construcciones.