27 votes

Que fait "select((select(s),$|=1)[0])" en Perl ?

J'ai vu des codes horribles écrits en Perl mais je n'arrive pas à comprendre celui-là :

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

C'est dans un code 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 (puisqu'il définit $| ).

Mais je n'arrive pas à comprendre pourquoi il y a plusieurs select ou la référence du tableau. Quelqu'un peut-il m'aider ?

59voto

Dan Points 20968

Il s'agit d'un petit idiome pour définir l'autoflush sur un gestionnaire de fichier autre que STDOUT.

select() prend le fichier fourni et remplace (basiquement) STDOUT par celui-ci, et retourne l'ancien fichier quand il a terminé.

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

Mais maintenant que vous le comprenez (enfin, peut-être ;)), faites plutôt ceci :

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

28voto

brian d foy Points 71781

La façon de comprendre un code est de le décortiquer. Vous savez que ce qui est à l'intérieur des parenthèses se passe avant ce qui est à l'extérieur. C'est la même façon de comprendre 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 les résultats de deux opérations : l'une pour sélectionner le s par défaut, puis un pour définir $| à une valeur vraie. Le site $| est l'une des variables per-filehandle qui ne s'appliquent qu'au filehandle actuellement sélectionné (voir Comprendre les variables globales en Le Perleur efficace ). Au final, vous obtenez une liste de deux éléments : le précédent filehandle par défaut (le résultat de la commande select ), et 1.

La partie suivante est une tranche de liste littérale pour extraire l'élément à l'indice 0 :

( PREVIOUS_DEFAULT, 1 )[0]

Le résultat est l'élément unique qui est le précédent filehandle par défaut.

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

 select( PREVIOUS_DEFAULT );

Donc, en fait, vous avez mis $| sur un fichier et vous vous êtes retrouvé au point de départ avec le fichier par défaut.

18voto

KennyTM Points 232647
select($fh)

Sélectionnez une nouvelle poignée 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]

Retourne la première valeur de ce tuple.

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

select c'est-à-dire restaurer l'ancien gestionnaire de fichiers par défaut.


Équivalent à

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

ce qui signifie

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

comme démontré dans la page perldoc.

8voto

Andy Lester Points 34051

C'est un code très astucieux pour activer le vidage de la mémoire tampon sur les manipulations. s puis en re-sélectionnant la poignée actuelle.

Ver perldoc -f select pour plus.

8voto

Aristotle Pagaltzis Points 43253

Dans un autre lieu, j'ai proposé une fois qu'une version plus compréhensible serait ainsi :

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

Cela préserve le seul avantage de l'idiome compact, à savoir qu'aucune variable ne doit être déclarée dans la portée environnante.

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

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

Le champ d'application de la $prevfh est limitée à la for bloc. (Mais si vous écrivez Perl, vous n'avez vraiment aucune excuse pour être frileux à propos de $_ .)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X