perl select buffering

¿Qué hace "seleccionar((seleccionar(s), $ |=1)[0])" hacer en Perl?



select buffering (7)

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

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

Está en algún código de red que utilizamos 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 de select o la referencia de matriz. ¿Puede alguien ayudarme?


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

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

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

O si no se siente cómodo con $_ , puede escribirlo así:

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

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


Es demasiado optimizado omitir la carga de IO :: Handle.

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

es mucho más legible


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

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


Es una pequeña expresión desagradable para configurar autoflush en una maneta 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 anterior cuando termina.

Entonces (select($s),$|=1) redirige el identificador de archivo (recuerda que select devuelve el anterior), y establece autoflush ( $| = 1 ). Hace esto en una lista ( (...)[0] ) y devuelve el primer valor (que es el resultado de la llamada de select - el STDOUT original), y luego lo transfiere a otro select para restablecer el archivo original STDOUT handlehandle . Uf.

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

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


La forma de descubrir cualquier código es separarlo. Sabes que las cosas entre paréntesis ocurren antes que las cosas afuera. Esta es la misma forma en que averiguaba qué código está haciendo 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 por defecto, luego uno para establecer $| a un verdadero valor. El $| es una de las variables por manejador de archivos que solo se aplica a la manejador de archivos seleccionada 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 es el elemento único que es el identificador de archivo predeterminado anterior.

La siguiente parte toma el resultado del corte y lo usa como argumento para otra llamada para select

select( PREVIOUS_DEFAULT );

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



select($fh)

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

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

Encienda autoflush. Ver http://perldoc.perl.org/perlvar.html

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

Devuelve el primer valor de esta tupla.

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

select , es decir, restaure el antiguo manejador de archivo predeterminado.

Equivalente a

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

lo que significa

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

como se demostró en la página de perldoc.