Что значит " 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);

гораздо более читабельно.