Cosa significa & # 8220; select ((seleziona (s), $ | = 1) [0]) & # 8221; fare in Perl?

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

  •  10-07-2019
  •  | 
  •  

Domanda

Ho visto del codice orribile scritto in Perl, ma non riesco a capirlo né a seguirlo:

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

È in alcuni codici di rete che utilizziamo per comunicare con un server e presumo che abbia a che fare con il buffering (poiché imposta $ | ).

Ma non riesco a capire perché ci siano più chiamate select o il riferimento dell'array. Qualcuno può darmi una mano?

È stato utile?

Soluzione

È un brutto idioma per impostare il flash automatico su un filehandle diverso da STDOUT.

select () prende il filehandle fornito e (sostanzialmente) sostituisce STDOUT con esso e restituisce il vecchio filehandle al termine.

Quindi (select ($ s), $ | = 1) reindirizza il filehandle (ricorda select restituisce quello vecchio) e imposta autoflush ( $ | = 1 ). Lo fa in un elenco ( (...) [0] ) e restituisce il primo valore (che è il risultato della chiamata select - lo STDOUT originale), e poi passa che in un altro seleziona per ripristinare il filehandle STDOUT originale. Uff.

Ma ora lo capisci (beh, forse;)), fallo invece:

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

Altri suggerimenti

Il modo per capire qualsiasi codice è di separarlo. Sai che le cose tra parentesi accadono prima delle cose fuori. Questo è lo stesso modo in cui capiresti cosa sta facendo il codice in altre lingue.

Il primo bit è quindi:

( select(s), $|=1 )

Quell'elenco ha due elementi, che sono i risultati di due operazioni: uno per selezionare il filehandle s come predefinito, poi uno per impostare $ | su un valore vero . Il $ | è una delle variabili per filehandle che si applicano solo al filehandle attualmente selezionato (vedi Comprendi le variabili globali in The Effective Perler ). Alla fine, hai un elenco di due elementi: il precedente filehandle predefinito (il risultato di seleziona ) e 1.

La parte successiva è una sezione di elenco letterale per estrarre l'elemento nell'indice 0:

( PREVIOUS_DEFAULT, 1 )[0]

Il risultato è il singolo elemento che è il precedente filehandle predefinito.

La parte successiva prende il risultato della sezione e la usa come argomento per un'altra chiamata a seleziona

 select( PREVIOUS_DEFAULT );

Quindi, in effetti, hai impostato $ | su un filehandle e sei finito dove hai iniziato con il filehandle predefinito.

select($fh)

Seleziona un nuovo handle di file predefinito. Vedi http://perldoc.perl.org/functions/select.html

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

Attiva autoflush. Vedi http://perldoc.perl.org/perlvar.html

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

Restituisce il primo valore di questa tupla.

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

seleziona , ovvero ripristina il vecchio handle di file predefinito.


Equivalente a

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

che significa

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

come dimostrato nella pagina perldoc.

In un'altra sede, una volta ho proposto che una versione più comprensibile sarebbe così:

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

In un'altra sede, una volta ho proposto che una versione più comprensibile sarebbe così:

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

Ciò preserva l'unico idioma compatto del fatto che nessuna variabile deve essere dichiarata nell'ambito circostante.

O se non sei a tuo agio con $ _ , puoi scriverlo in questo modo:

<*>

L'ambito di $ prevfh è limitato al blocco for . (Ma se scrivi Perl non hai davvero scuse per essere scaltro su $ _ .)

}

Ciò preserva l'unico idioma compatto del fatto che nessuna variabile deve essere dichiarata nell'ambito circostante.

O se non sei a tuo agio con $ _ , puoi scriverlo in questo modo:

<*>

L'ambito di $ prevfh è limitato al blocco for . (Ma se scrivi Perl non hai davvero scuse per essere scaltro su $ _ .)

È un codice eccessivamente intelligente per attivare lo svuotamento del buffer sull'handle s e quindi selezionare nuovamente l'handle corrente.

Vedi perldoc -f select per altro.

controlla perldoc -f seleziona . Per il significato di $ | , controlla perldoc perlvar

È un'ottimizzazione eccessiva saltare il caricamento di IO :: Handle.

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

è molto più leggibile.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top