Pregunta

He visto un código horrible escrito en Perl, pero no puedo hacer ni la cabeza ni la cola de este:

select((select(s),$|=1)[0])

Está en algún código de red que usamos para comunicarnos con un servidor y supongo que tiene algo que ver con el almacenamiento en búfer (ya que establece $ | ).

Pero no puedo entender por qué hay múltiples llamadas select o la referencia de la matriz. ¿Alguien puede ayudarme?

¿Fue útil?

Solución

Es un idioma poco asqueroso para configurar el lavado automático en un controlador de archivo que no sea STDOUT.

select () toma el identificador de archivo suministrado y (básicamente) reemplaza STDOUT con él, y devuelve el identificador de archivo antiguo cuando está hecho.

Entonces (select ($ s), $ | = 1) redirige el identificador de archivo (recuerde que select devuelve el antiguo), y establece el enjuague automático ( $ | = 1 ). Lo hace en una lista ( (...) [0] ) y devuelve el primer valor (que es el resultado de la llamada select - el STDOUT original), y luego pasa que nuevamente a otra select para restablecer el identificador de archivo STDOUT original. Uf.

Pero ahora lo entiendes (bueno, tal vez;)), haz esto en su lugar:

use IO::Handle;
$fh->autoflush;

Otros consejos

La forma de descifrar cualquier código es separarlo. Sabes que las cosas dentro de paréntesis ocurren antes que las cosas afuera. Esta es la misma forma en que descubrirías qué está haciendo el código en otros idiomas.

El primer bit es entonces:

( select(s), $|=1 )

Esa lista tiene dos elementos, que son el resultado de dos operaciones: una para seleccionar el identificador de archivo s como predeterminado y luego uno para establecer $ | en un valor verdadero . El $ | es una de las variables por identificador de archivo que solo se aplica al identificador de archivo seleccionado actualmente (consulte Comprender las variables globales en The Effective Perler ). Al final, tiene una lista de dos elementos: el identificador de archivo predeterminado anterior (el resultado de select ) y 1.

La siguiente parte es un segmento de lista literal para extraer el elemento en el índice 0:

( PREVIOUS_DEFAULT, 1 )[0]

El resultado de eso es el único elemento que es el identificador de archivo predeterminado anterior.

La siguiente parte toma el resultado del segmento y lo usa como argumento para otra llamada a seleccion

 select( PREVIOUS_DEFAULT );

Entonces, en efecto, configuró $ | en un identificador de archivo y terminó donde comenzó con el identificador de archivo predeterminado.

select($fh)

Seleccione un nuevo identificador de archivo predeterminado. Ver http://perldoc.perl.org/functions/select.html

(select($fh), $|=1)

Active el lavado automático. Ver http://perldoc.perl.org/perlvar.html

(select($fh), $|=1)[0]

Devuelve el primer valor de esta tupla.

select((select($fh), $|=1)[0])

seleccionar , es decir, restaurar el antiguo identificador de archivo predeterminado.


Equivalente a

$oldfh = select($fh);
$| = 1;
select($oldfh);

que significa

use IO::Handle;
$fh->autoflush(1);

como se demuestra en la página perldoc.

En otro lugar, una vez propuse que una versión más comprensible sería así:

for ( select $fh ) { $| = 1; select 

En otro lugar, una vez propuse que una versión más comprensible sería así:

for my $prevfh ( select $fh ) { $| = 1; select $prevfh }

Esto preserva la única ventaja del idioma compacto de que no es necesario declarar ninguna variable en el ámbito circundante.

O si no está cómodo con $ _ , puede escribirlo así:

<*>

El alcance de $ prevfh está limitado al bloque for . (Pero si escribes Perl, realmente no tienes excusa para asustarte de $ _ .)

}

Esto preserva la única ventaja del idioma compacto de que no es necesario declarar ninguna variable en el ámbito circundante.

O si no está cómodo con $ _ , puede escribirlo así:

<*>

El alcance de $ prevfh está limitado al bloque for . (Pero si escribes Perl, realmente no tienes excusa para asustarte de $ _ .)

Es un código demasiado inteligente para activar el lavado del búfer en el controlador s y luego volver a seleccionar el controlador actual.

Consulte perldoc -f select para obtener más información.

compruebe perldoc -f select . Para conocer el significado de $ | , consulte perldoc perlvar

Es una sobreoptimización omitir la carga de IO :: Handle.

use IO::Handle;
$fh->autoflush(1);

es mucho más legible.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top