Что означает "select ((select (s), $| = 1) [0])" делать в Perl?
Я видел какой-то ужасный код, написанный на Perl, но я не могу сделать голову или хвост этого:
select((select(s),$|=1)[0])
Это в каком-то сетевом коде, который мы используем для связи с сервером, и я предполагаю, что это что-то связано с буферизацией (поскольку оно устанавливает $|
).
Но я не могу понять, почему существует несколько вызовов select
или ссылка на массив. Может ли кто-нибудь помочь мне?
Ответы
Ответ 1
Это неприятная маленькая идиома для установки autoflush на дескрипторе файла, отличном от STDOUT.
select()
принимает прилагаемый дескриптор файла и (в основном) заменяет его STDOUT, и он возвращает старый дескриптор файла, когда это делается.
Итак (select($s),$|=1)
перенаправляет дескриптор файла (помните select
возвращает старый) и устанавливает autoflush ($| = 1
). Он делает это в списке ((...)[0]
) и возвращает первое значение (которое является результатом вызова select
- исходный STDOUT), а затем передает это обратно в другой select
, чтобы восстановить исходный дескриптор файла STDOUT. Уф.
Но теперь вы это понимаете (ну, может быть;)), сделайте это вместо этого:
use IO::Handle;
$fh->autoflush;
Ответ 2
Способ выяснить любой код - выделить его. Вы знаете, что материал в круглых скобках случается раньше, чем на улице. Точно так же вы выясните, что делает код на других языках.
Первый бит:
( select(s), $|=1 )
В этом списке есть два элемента, которые являются результатом двух операций: один для выбора дескриптора файла s
в качестве значения по умолчанию, а затем для установки $|
истинному значению. $|
является одной из переменных дескриптора для каждого файла, которые применяются только к выбранному в данный момент дескриптору файла (см. Понять глобальные переменные в Эффективный Perler). В итоге у вас есть список из двух элементов: предыдущий дескриптор файла по умолчанию (результат select
) и 1.
Следующая часть представляет собой литеральный список списка, чтобы вытащить элемент в индексе 0:
( PREVIOUS_DEFAULT, 1 )[0]
В результате это единственный элемент, который является предыдущим файловым дескриптором по умолчанию.
Следующая часть берет результат среза и использует его в качестве аргумента для другого вызова select
select( PREVIOUS_DEFAULT );
Итак, вы установили $|
в дескриптор файла и вернулись туда, где вы начали с дескриптора файла по умолчанию.
Ответ 3
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
это, т.е. восстановить старый дескриптор файла по умолчанию.
Эквивалентно
$oldfh = select($fh);
$| = 1;
select($oldfh);
что означает
use IO::Handle;
$fh->autoflush(1);
как показано на странице perldoc.
Ответ 4
В другом месте я однажды предложил, чтобы более понятная версия была таким образом:
for ( select $fh ) { $| = 1; select $_ }
Это сохраняет единственное преимущество компактных идиом, что никакая переменная не должна быть объявлена в окружении.
Или, если вам не комфортно с $_
, вы можете написать его вот так:
for my $prevfh ( select $fh ) { $| = 1; select $prevfh }
Объем $prevfh
ограничен блоком for
. (Но если вы пишете Perl, у вас действительно нет оправдания, чтобы быть пугливым о $_
.)
Ответ 5
Это слишком умный код для включения сброса буфера на дескрипторе s
, а затем повторного выбора текущего дескриптора.
Подробнее см. perldoc -f select
.
Ответ 6
проверьте perldoc -f выберите. Для значения $|
, пожалуйста, проверьте perldoc perlvar
Ответ 7
Это переоптимизация, чтобы пропустить загрузку IO:: Handle.
use IO::Handle;
$fh->autoflush(1);
является более читаемым.