Was bedeutet "select((select(s),$|=1)[0])" tun in Perl?
Ich habe gesehen, einige schrecklichen code in Perl geschrieben, aber ich kann nicht Kopf noch Schwanz der eine:
select((select(s),$|=1)[0])
Ist es in einigen Netzwerk-code, den wir verwenden, um die Kommunikation mit einem server, und ich vermute, es ist etwas zu tun mit Pufferung (da setzt es $|
).
Aber ich kann nicht herausfinden, warum es mehrere select
Anrufe oder die array-Referenz. Kann jemand mir helfen?
- Zu verwirren und zu frustrieren Menschen, die haben, den code zu pflegen, D. H. Sie.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Es ist eine böse kleine idiom für die Einstellung autoflush auf ein filehandle andere als STDOUT.
select()
nimmt das filehandle geliefert und (im Grunde) ersetzt STDOUT, und es gibt die alten filehandle, wenn es fertig ist.So
(select($s),$|=1)
leitet das filehandle (denken Sie daranselect
gibt die alte), und setzt autoflush ($| = 1
). Es tut dies in einer Liste ((...)[0]
) und gibt den ersten Wert (was ist das Ergebnis derselect
nennen - das original STDOUT), und dann geht , dass wieder in einem anderenselect
Wiederinstandsetzung der ursprünglichen STDOUT filehandle. Puh.Aber jetzt verstehen Sie es (gut, vielleicht ;)), tun Sie dies:
for
zu topicalise der alte Griff für re-Auswahl. Siehe meine Antwort.perl -wE 'open OUTPUT, ">", undef; say select(OUTPUT)'
nicht ausdrucken main::STDOUT. Warum?say
ist ein filehandle 😉 Versuchensay STDOUT select(OUTPUT)
.Den Weg, um herauszufinden, jeder code ist zu pflücken es auseinander. Sie wissen, dass die Sachen in Klammern geschieht, bevor Sie Sachen draußen. Dies ist die gleiche Weise würden Sie, herauszufinden, was der code tut in anderen Sprachen.
Das erste bit ist dann:
Diese Liste hat zwei Elemente, die die Ergebnisse von zwei Operationen: eine, um die wählen Sie die
s
filehandle als Standard, dann einer, um$|
einen wahren Wert. Die$|
ist eines der pro-filehandle-Variablen, die gelten nur für die aktuell ausgewählte filehandle (siehe Verstehen von globalen Variablen bei Die Effektive Perler). Am Ende haben Sie eine Liste von zwei Elementen: der bisherige Standard-filehandle (das Ergebnisselect
), und 1.Der nächste Teil ist ein literal-Liste slice ziehen Sie das Element bei index 0:
Dem Ergebnis, dass ist das einzige Element, das frühere Standard-filehandle.
Den nächsten Teil dauert, das Ergebnis an die Scheibe und benutzt es als argument, um einen weiteren Anruf zu
select
So, in Wirkung, die Sie sich gesetzt haben
$|
auf ein filehandle und landete wieder dort, wo Sie begonnen mit der Standard-filehandle.Wählen Sie eine neue Standard-Datei-handle. Sehen http://perldoc.perl.org/functions/select.html
Schalten autoflush. Sehen http://perldoc.perl.org/perlvar.html
Rückkehr der erste Wert des Tupels.
select
es, D. H. wiederherstellen der alten Standard-Datei-handle.Entspricht
was bedeutet
gezeigt, in der perldoc Seite.
IO::Handle
die am wenigsten Sie tun könnten, ist, wickeln Sie diese Monstrosität in einer Funktion wiesub flush ($) { select((select($_[0]), $|=1)[0]); }
flush
Funktion jemals zu ändern. Vielleicht ist die schreckliche version ist etwas schneller. Vielleicht können Sie es verwenden, um zu erschrecken Praktikant.In einem anderen Ort, ich habe einmal vorgeschlagen, dass eine mehr verständliche version wäre also:
Dadurch bleibt die kompakte idiom alleinigen Vorteil, dass keine variable muss deklariert werden in den umgebenden Bereich.
Oder wenn Sie sich nicht wohl mit
$_
können Sie schreiben es so:Den Umfang der
$prevfh
beschränkt sich auf diefor
block. (Aber wenn Sie schreiben, Perl Sie haben wirklich keine Ausrede mehr scheu über$_
.)Es ist übermäßig clever-code für das einschalten buffer-flushing auf Griff
s
und dann re-Auswahl der aktuellen Griff.Sehen
perldoc -f select
für mehr.bitte überprüfen Sie perldoc -f select. Für die Bedeutung von
$|
, überprüfen Sie bitte perldoc perlvarIst es overoptimization zu überspringen, laden IO::Handle.
ist sehr viel besser lesbar.