Что значит " select ((select (S),$|=1)[0])" делать в Perl?
Я видел какой-то ужасный код, написанный на Perl, но я не могу понять, что это такое:
select((select(s),$|=1)[0])
Это в некотором сетевом коде, который мы используем для связи с сервером, и я предполагаю, что это связано с буферизацией (поскольку она устанавливает $|
).
но я не могу понять, почему есть несколько select
вызовы или ссылка на массив. Кто-нибудь может мне помочь?
7 ответов
это неприятная маленькая идиома для установки автозапуска на ручке файла, кроме STDOUT.
select()
берет предоставленную файловую ручку и (в основном) заменяет ею STDOUT, и она возвращает старую файловую ручку, когда это сделано.
так (select($s),$|=1)
перенаправляет файловую ручку (помните select
возвращает старый), и устанавливает автосброс ($| = 1
). Он делает это в списке ((...)[0]
) и возвращает первое значение (которое является результатом select
call-оригинальный STDOUT), а потом проходит это в другой select
для восстановления исходного файла STDOUT. Фу.
но теперь вы понимаете это (ну, может быть;)), сделайте это вместо этого:
use IO::Handle;
$fh->autoflush;
способ выяснить любой код-это разобрать его на части. Вы знаете, что вещи внутри скобок происходят до того, как вещи снаружи. Таким же образом вы выясняете, что код делает на других языках.
первый бит-это значит:
( select(s), $|=1 )
этот список имеет два элемента, которые являются результатами двух операций: один для выбора s
filehandle по умолчанию, а затем один, чтобы установить $|
истинному значению. The $|
является одной из переменных для каждого файла которые применимы только к выбранному файлу (см. понять глобальные переменные at Эффективный Perler). В конце концов, у вас есть список из двух элементов: предыдущий файл по умолчанию (результат select
), и 1.
следующая часть является буквальным срезом списка, чтобы вытащить элемент в индексе 0:
( PREVIOUS_DEFAULT, 1 )[0]
результатом этого является один элемент, который является предыдущим по умолчанию filehandle.
следующая часть принимает результат и использует его в качестве аргумента для другого вызова select
select( PREVIOUS_DEFAULT );
Итак, по сути, вы установили $|
на filehandle и оказался там, где вы начали с файловой ручки по умолчанию.
select($fh)
выберите новый дескриптор файла по умолчанию. См.http://perldoc.perl.org/functions/select.html
(select($fh), $|=1)
включить автосброс. См.http://perldoc.perl.org/perlvar.html
(select($fh), $|=1)[0]
возвращает первое значение этого кортежа.
select((select($fh), $|=1)[0])
select
it, т. е. восстановить старый дескриптор файла по умолчанию.
эквивалентно
$oldfh = select($fh);
$| = 1;
select($oldfh);
что означает
use IO::Handle;
$fh->autoflush(1);
as продемонстрировано на странице perldoc.
в другом месте я однажды предложил, чтобы более понятная версия была такой:
for ( select $fh ) { $| = 1; select $_ }
это сохраняет единственное преимущество компактной идиомы, что никакая переменная не должна быть объявлена в окружающей области.
или если вам неудобно с $_
можно написать так:
for my $prevfh ( select $fh ) { $| = 1; select $prevfh }
объем $prevfh
ограничен for
блок. (Но если вы пишете Perl, у вас действительно нет оправдания быть пугливым о $_
.)
это слишком умный код для включения промывки буфера на ручке s
и снова-выбор текущей ручкой.
посмотреть perldoc -f select
дополнительные.
пожалуйста, проверьте perldoc-f выберите. Смысла $|
, проверьте, пожалуйста perldoc perlvar
это сверхоптимизация, чтобы пропустить загрузку IO:: Handle.
use IO::Handle;
$fh->autoflush(1);
гораздо более читабельно.