O que significa “escolha ((select (s), $ | = 1) [0])” fazer em Perl?
Pergunta
Eu vi algum código horrível escrito em Perl, mas eu não posso fazer pé nem cabeça de um presente:
select((select(s),$|=1)[0])
É em algum código de rede que usamos para se comunicar com um servidor e eu supor que é algo a ver com o buffer (uma vez que define $|
).
Mas eu não consigo descobrir por que há várias chamadas select
ou a referência de matriz. Alguém pode me ajudar?
Solução
É um estilo pouco desagradável para definir autoflush em um outro filehandle de STDOUT.
select()
leva o filehandle fornecido e (basicamente) substitui STDOUT com ele, e ele retorna a velha filehandle quando ele é feito.
Assim (select($s),$|=1)
redireciona o filehandle (lembre-se select
retorna o antigo), e conjuntos autoflush ($| = 1
). Ele faz isso de uma lista ((...)[0]
) e retorna o primeiro valor (que é o resultado da chamada select
- o STDOUT original), e, em seguida, passa que de volta para outra select
para restabelecer o filehandle STDOUT originais . Ufa.
Mas agora você entendê-lo (bem, talvez;)), fazer isso em vez disso:
use IO::Handle;
$fh->autoflush;
Outras dicas
A maneira de descobrir qualquer código é para pegá-lo distante. Você sabe que o material dentro de parênteses acontece antes fora coisas. Esta é a mesma maneira que você descobrir o que o código está fazendo em outros idiomas.
O primeiro bit é então:
( select(s), $|=1 )
Essa lista tem dois elementos, que são os resultados de duas operações: uma para selecionar o filehandle s
como padrão, em seguida, um para definir $|
a um verdadeiro valor. O $|
é uma das variáveis ??per-FileHandle que só se aplicam ao filehandle atualmente selecionado (veja Entenda variáveis ??globais em O Perler eficaz ). No final, você tem uma lista de dois itens:. Filehandle padrão anterior (o resultado de select
) e 1
A próxima parte é uma lista literal fatia para retirar o item no índice 0:
( PREVIOUS_DEFAULT, 1 )[0]
O resultado disso é o único item que é filehandle padrão anterior.
A próxima parte leva o resultado da fatia e usa como argumento para outra chamada para select
select( PREVIOUS_DEFAULT );
Então, na verdade, você tem $|
set em um filehandle e acabou de volta onde você começou com o filehandle padrão.
select($fh)
Selecione um novo identificador de arquivo padrão. Consulte http://perldoc.perl.org/functions/select.html
(select($fh), $|=1)
Ligue autoflush. Consulte http://perldoc.perl.org/perlvar.html
(select($fh), $|=1)[0]
retornar o primeiro valor desta tupla.
select((select($fh), $|=1)[0])
select
-lo, ou seja, restaurar o antigo identificador de arquivo padrão.
Equivalente a
$oldfh = select($fh);
$| = 1;
select($oldfh);
que meios
use IO::Handle;
$fh->autoflush(1);
como demonstrado na página perldoc.
Em outro local, uma vez eu propôs que uma versão mais compreensível seria assim:
for ( select $fh ) { $| = 1; select $_ }
Isso preserva única vantagem do idioma compacto que há necessidades variáveis ??ser declaradas no âmbito circundante.
Ou se você não está confortável com $_
, você pode escrevê-lo como este:
for my $prevfh ( select $fh ) { $| = 1; select $prevfh }
O escopo de $prevfh
é limitado ao bloco for
. (Mas se você escrever Perl você realmente não tem desculpa para estar nervosos sobre $_
.)
É o código excessivamente inteligente para ligar rubor tampão em s
alça e, em seguida, re-selecionando a alça de corrente.
Veja perldoc -f select
para mais.
perldoc -f selecionar . Para o significado de $|
, verifique perldoc perlvar
É overoptimization para pular o carregamento IO :: Handle.
use IO::Handle;
$fh->autoflush(1);
é muito mais legível.