Что выбирает ((выберите (ы), $ | = 1) [0]) & # 8221; делать в Perl?

StackOverflow https://stackoverflow.com/questions/196754

  •  10-07-2019
  •  | 
  •  

Вопрос

Я видел какой-то ужасающий код, написанный на Perl, но я не могу понять, как это сделать:

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

Это некоторый сетевой код, который мы используем для связи с сервером, и я предполагаю, что это как-то связано с буферизацией (поскольку она устанавливает $ | ).

Но я не могу понять, почему существует несколько вызовов select или ссылка на массив. Кто-нибудь может мне помочь?

Это было полезно?

Решение

Это небольшая неприятная идиома для установки автозаполнения для файлового дескриптора, отличного от STDOUT.

select () берет предоставленный файловый дескриптор и (в основном) заменяет им STDOUT и возвращает старый файловый дескриптор, когда это сделано.

Итак, (select ($ s), $ | = 1) перенаправляет дескриптор файла (помните, select возвращает старый) и устанавливает автозапуск ( $ | = 1 ). Он делает это в списке ( (...) [0] ) и возвращает первое значение (которое является результатом вызова select - исходный STDOUT), а затем передает это обратно в другой select , чтобы восстановить исходный дескриптор файла STDOUT. Уф.

Но теперь вы понимаете это (ну, может быть;)), сделайте это вместо этого:

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

Другие советы

Способ выяснить любой код - это выделить его. Вы знаете, что вещи внутри скобок происходят раньше, чем вещи снаружи. Это так же, как вы выясните, что код делает на других языках.

Тогда первый бит:

( select(s), $|=1 )

Этот список содержит два элемента, которые являются результатом двух операций: один для выбора дескриптора файла s в качестве значения по умолчанию, а второй - для установки для $ | истинного значения. , $ | - это одна из переменных для каждого дескриптора файла, которая применяется только к текущему выбранному дескриптору файла (см. Понимать глобальные переменные в Эффективном Perler ). В итоге у вас есть список из двух элементов: предыдущий дескриптор файла по умолчанию (результат select ) и 1.

Следующая часть - это буквальный фрагмент списка для извлечения элемента с индексом 0:

( PREVIOUS_DEFAULT, 1 )[0]

Результатом этого является один элемент, который является предыдущим дескриптором файла по умолчанию.

Следующая часть берет результат среза и использует его в качестве аргумента для другого вызова select

 select( PREVIOUS_DEFAULT );

Итак, по сути, вы установили $ | для файлового дескриптора и в итоге вернулись к тому, с чего начали с файловым дескриптором по умолчанию.

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])

выберите , то есть восстановите старый дескриптор файла по умолчанию.

<Ч>

Эквивалент

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

что означает

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

как показано на странице perldoc.

В другом месте я однажды предложил, чтобы более понятная версия была такой:

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

В другом месте я однажды предложил, чтобы более понятная версия была такой:

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

Это сохраняет единственное преимущество компактной идиомы, заключающееся в том, что в окружающей области не нужно объявлять переменные.

Или, если вам не нравится $ _ , вы можете написать это так:

<*>

Область действия $ prevfh ограничена блоком for . (Но если вы напишите на Perl, у вас действительно не будет повода быть осторожным в отношении $ _ .)

}

Это сохраняет единственное преимущество компактной идиомы, заключающееся в том, что в окружающей области не нужно объявлять переменные.

Или, если вам не нравится $ _ , вы можете написать это так:

<*>

Область действия $ prevfh ограничена блоком for . (Но если вы напишите на Perl, у вас действительно не будет повода быть осторожным в отношении $ _ .)

Это слишком умный код для включения очистки буфера на дескрипторе s и повторного выбора текущего дескриптора.

Подробнее см. perldoc -f select .

пожалуйста, проверьте perldoc -f select . Значение $ | см. В разделе perldoc perlvar

Это чрезмерная оптимизация, чтобы пропустить загрузку IO :: Handle.

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top