Es una convención para evitar el uso $ _ cuando se utiliza de Perl API de otras personas?

StackOverflow https://stackoverflow.com/questions/4054611

  •  27-09-2019
  •  | 
  •  

Pregunta

acabo de estar atrapado cuando se utiliza la API de otra persona en relación con la variable por defecto $ _

foreach (@rps_server_details) {
    @server_data = ();
    @server_data = split(/,/);
    @$esp_hosts = ();
    $filters{server_name} = $server_data[0];
    print "--->$_<--\n";
    $esp_hosts = $esp->get_hosts(fields => $fields, %filters) || die "$@";
    print "--->$_<--\n";

La salida para este es:

--->igrid8873.someone.com,app_10<--
Use of uninitialized value in concatenation (.) or string at ./rps_inv_lookup.pl line 120.
---><--

Especificación de mi propia variable de bucle en lugar de depender $ _ soluciona el problema.

¿Estoy siendo ingenua utilizando $ _ junto con una API alguien más ha escrito? O se trata de un error en ese módulo API?

¿Fue útil?

Solución

Se trata de un error en la API. Si utiliza $_ en una función que es importante añadir un

local($_);

dentro de la función de evitar clobbering $_ de la persona que llama, o de otra manera evitar el uso de $_in una función de biblioteca para ser llamado por otros.

Si se puede limitar a yoursel versiones de Perl> 5.9.1 a continuación, también se puede hacer $ _ léxica que hace que sea más fácil de entender que localwith

my $_;

Pero esto va a romper en las versiones anteriores de Perl.

Desde el hombre perlvar:

  

Como $_ es una variable global, esto puede llevar en algunos casos a                  efectos secundarios no deseados. A partir de Perl 5.9.1, ahora puede usar una                  Versión léxica de $_ al declarar en un archivo o en un bloque                  con mi". Por otra parte, se declara "our $_" restaura la $_ mundial                  en el ámbito actual.

Otros consejos

Yo diría que es:

  1. una violación de las mejores prácticas de su parte (siempre use como local, como el posible alcance variable y evitar el uso de $_ debido a sólo el tema de su encontrado)

  2. junto con un error en la API causada por la misma violación de las mejores prácticas, así como no localizar la variable especial con local $_ como proscrito por perldoc perlvar .

Además de perldoc, la API Perl viola las mejores prácticas (como en las reglas del libro de Conway):

  

Sección 5.6. Las variables que localiza a la puntuación

     

Si uno se ve obligado a modificar una variable puntuacion, localizarla.

     

Los problemas descritos anteriormente bajo "La localización también puede surgir cuando uno se ve obligado a cambiar el valor de una variable puntuacion (a menudo en las operaciones de E / S). Todas las variables de puntuación son de alcance mundial. Proporcionan control explícito sobre lo sería comportamientos completamente implícitas en la mayoría de los otros idiomas:. búfer de salida, la numeración de línea de entrada, la entrada y la línea de salida finales, matriz de indexación, etcétera

     

Por lo general es un grave error para cambiar una variable puntuacion sin antes localizarlo. asignaciones no localizadas pueden potencialmente cambiar el comportamiento del código en partes desvinculadas de su sistema, incluso en módulos que no escribió a sí mismo, sino que simplemente utilizando.

     

El uso local es la manera más limpia y más robusto para cambiar temporalmente el valor de una variable global. Siempre se debe aplicar en el más pequeño alcance posible, a fin de minimizar los efectos de cualquier "comportamiento ambiental" la variable puede controlar:

Aquí está llena perldoc perlvar documentación, así - búsqueda de la palabra "nasty_break "en la página web (no pude encontrar enlace directo en la página pero está cerca del comienzo de la página)

  

Se debe tener mucho cuidado cuando   modificar los valores por defecto de la mayoría   las variables especiales que se describen en este   documento. En la mayoría de los casos que desea   localizar estas variables antes   cambiarlas, ya que si no lo hace, el   cambio puede afectar a otros módulos que   confiar en los valores por defecto del   variables especiales que usted tiene   cambiado. Este es uno de los más correcta   formas de leer todo el archivo a la vez:

     
      
  1. abrir mi $ fh, "<", "foo" o morir $ !;
  2.   
  3. $ locales /; # Activar el modo cómo sorber localizada
  4.   
  5. $ content = mi;
  6.   
  7. cerrar $ fh;
  8.   
     

Sin embargo, el siguiente código es bastante malo:

     
      
  1. abrir mi $ fh, "<", "foo" o morir $ !;
  2.   
  3. $ undef /; # Activar el modo cómo sorber
  4.   
  5. $ content = mi;
  6.   
  7. cerrar $ fh;
  8.   
     

desde algún otro módulo, puede querer   leer datos de algún archivo en el   Por defecto "modo de línea", por lo que si el código   se acaba de presentar ha sido ejecutado,   el valor global de $ / ahora ha cambiado   para cualquier otro código que se ejecuta dentro de la   mismo intérprete Perl.

     

Por lo general, cuando se localiza una variable   usted quiere asegurarse de que este cambio   afecta posible el alcance más corto.   Así que a menos que ya está dentro de algunos   {} bloque corto, se debe crear una   usted mismo. Por ejemplo:

     
      
  1. mi $ content = '';
  2.   
  3. abrir mi $ fh, "<", "foo" o morir $ !;
  4.   
  5. {
  6.   
  7. $ locales /;
  8.   
  9. $ content =;
  10.   
  11. }
  12.   
  13. cerrar $ fh;
  14.   
     

Este es un ejemplo de cómo su propia   código puede ir roto:

     
      
  1. para (1..5) {
  2.   
  3. nasty_break ();
  4.   
  5. imprimir "$ _";
  6.   
  7. }
  8.   
  9. sub nasty_break {
  10.   
  11. $ _ = 5;
  12.   
  13. # hacer algo con $ _
  14.   
  15. }
  16.   
     

Es probable que esperar a este código   imprimir:

     
      
  1. 12 3 4 5
  2.   
     

sino que se obtiene:

     
      
  1. 5 5 5 5 5
  2.   
     

¿Por qué? Debido nasty_break () modifica $ _   sin localizar primero. La solución   es añadir local ():

     
      
  1. $ _ locales = 5;
  2.   
foreach (@rps_server_details) {
    @server_data = ();
    @server_data = split(/,/);
    @$esp_hosts = ();
    $filters{server_name} = $server_data[0];
    print "--->$_<--\n";
    {
        local *_;  # disconnects the remaining scope from the implicit 
                   # variables so you can clean up after the dirty api.
                   # NOTE: Submit a bug report against the offending module.
                   #       If you notice this across multiple api features
                   #       consider finding a different module for this task.
        $esp_hosts = $esp->get_hosts(fields => $fields, %filters) || die "$@";
    }
    print "--->$_<--\n";
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top