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?

Foi útil?

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.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top