Question

J'ai vu un code horrible écrit en Perl, mais je ne peux pas en faire la tête ni la queue:

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

C’est dans certains codes de réseau que nous utilisons pour communiquer avec un serveur et je suppose que cela a quelque chose à voir avec la mise en mémoire tampon (car elle définit $ | ).

Mais je ne comprends pas pourquoi il existe plusieurs appels select ou la référence du tableau. Quelqu'un peut-il m'aider?

Était-ce utile?

La solution

C’est un vilain petit idiome pour régler le flash automatique sur un autre fichier que STDOUT.

select () prend le descripteur de fichier fourni et remplace (en gros) STDOUT par celui-ci, et renvoie l'ancien descripteur lorsque c'est terminé.

Donc (select ($ s), $ | = 1) redirige le descriptif de fichier (rappelez-vous que select renvoie l'ancien), et définit autoflush ( $ | = 1 ). Il le fait dans une liste ( (...) [0] ) et renvoie la première valeur (qui est le résultat de l'appel select - le STDOUT d'origine), puis transmet que dans un autre sélectionnez pour rétablir le descripteur de fichier STDOUT d'origine. Ouf.

Mais maintenant vous le comprenez (enfin, peut-être;)), faites ceci à la place:

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

Autres conseils

Pour identifier un code, il faut le sélectionner. Vous savez que les choses entre parenthèses se passent avant celles à l'extérieur. C’est la même chose que de déterminer ce que fait le code dans d’autres langues.

Le premier bit est alors:

( select(s), $|=1 )

Cette liste comporte deux éléments, qui sont le résultat de deux opérations: une pour sélectionner le descripteur de fichier s comme valeur par défaut, une autre pour définir $ | sur une valeur vraie . Le $ | est l’une des variables par descripteur de fichier qui s’applique uniquement au descripteur de fichier actuellement sélectionné (voir Comprenez les variables globales dans The Perler effectif ). Au final, vous avez une liste de deux éléments: le descripteur de fichier par défaut précédent (le résultat de select ) et 1.

La partie suivante est une tranche de liste littérale permettant d'extraire l'élément dans l'index 0:

( PREVIOUS_DEFAULT, 1 )[0]

Le résultat est le seul élément qui est le descripteur de fichier par défaut précédent.

La partie suivante prend le résultat de la tranche et l'utilise comme argument d'un autre appel à select

 select( PREVIOUS_DEFAULT );

Donc, en réalité, vous avez défini $ | sur un descripteur de fichier et vous vous retrouvez à l'endroit où vous avez commencé avec le descripteur de fichier par défaut.

select($fh)

Sélectionnez un nouveau descripteur de fichier par défaut. Voir http://perldoc.perl.org/functions/select.html

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

Activez l'autoflush. Voir http://perldoc.perl.org/perlvar.html

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

Renvoie la première valeur de ce tuple.

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

sélectionnez , c’est-à-dire restaurez l’ancien descripteur de fichier par défaut.

Équivalent à

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

qui signifie

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

comme indiqué dans la page perldoc.

À une autre occasion, j'ai déjà proposé qu'une version plus compréhensible soit:

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

À une autre occasion, j'ai déjà proposé qu'une version plus compréhensible soit:

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

Cela préserve le seul avantage du langage compact qu’aucune variable n’a besoin d’être déclarée dans la portée environnante.

Ou si vous n'êtes pas à l'aise avec $ _ , vous pouvez l'écrire comme suit:

<*>

La portée de $ prevfh est limitée au bloc pour . (Mais si vous écrivez à Perl, vous n’avez vraiment aucune excuse pour parler de $ _ .)

}

Cela préserve le seul avantage du langage compact qu’aucune variable n’a besoin d’être déclarée dans la portée environnante.

Ou si vous n'êtes pas à l'aise avec $ _ , vous pouvez l'écrire comme suit:

<*>

La portée de $ prevfh est limitée au bloc pour . (Mais si vous écrivez à Perl, vous n’avez vraiment aucune excuse pour parler de $ _ .)

C’est un code trop astucieux pour activer le vidage de la mémoire tampon sur la poignée s , puis sélectionner à nouveau la poignée actuelle.

Voir perldoc -f, sélectionnez pour plus d'informations.

veuillez vérifier perldoc -f select . Pour connaître la signification de $ | , consultez la page perldoc perlvar

Il est suroptimisé de ne pas charger IO :: Handle.

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

est beaucoup plus lisible.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top