Какая магия стоит за функцией perl read () и буфером, который не является ссылкой? - PullRequest
6 голосов
/ 10 июня 2010

Я не понимаю, как функция Perl read ($ buf) может изменять содержимое переменной $ buf.$ buf не является ссылкой, поэтому параметр задается копией (насколько мне известно на языке c / c ++).Так почему же переменная $ buf изменяется в вызывающей программе?

Это переменная связи или что-то?Документация C о setbuf также довольно неуловима и неясна для меня

# Example 1
$buf=''; # It is a scalar, not a ref
$bytes = $fh->read($buf);
print $buf; # $buf was modified, what is the magic ?

# Example 2
sub read_it {
    my $buf = shift;
    return $fh->read($buf);
}
my $buf;
$bytes = read_it($buf);
print $buf; # As expected, this scope $buf was not modified

Ответы [ 2 ]

11 голосов
/ 10 июня 2010

Никакой магии не требуется - все подпрограммы perl являются псевдонимами вызовов, если хотите. Quoth perlsub :

Массив @_ является локальным массивом, но его элементы являются псевдонимами. для фактических скалярных параметров. В частности, если элемент $ _ [0] обновляется, соответствующий аргумент обновляется (или возникает ошибка если это не обновляется).

Например:

sub increment {
  $_[0] += 1;
}

my $i = 0;
increment($i);  # now $i == 1

В вашем "Примере 2" ваш read_it sub копирует первый элемент @_ в лексический $buf, и эта копия затем изменяется "на месте" при вызове read(). Передайте $_[0] вместо копирования и посмотрите, что произойдет:

sub read_this {
  $fh->read($_[0]);  # will modify caller's variable
}
sub read_that {
  $fh->read(shift);  # so will this...
}
0 голосов
/ 10 июня 2010

read() является встроенной функцией, и поэтому может творить чудеса.Однако вы можете сделать нечто подобное с вашими собственными функциями, объявив прототип функции :

sub myread(\$) { ... }

Объявление аргумента \$ означает, что аргумент неявно передается как ссылка.

Единственное волшебство во встроенном read заключается в том, что он работает даже при косвенном вызове или как метод дескриптора файла, который не работает для обычных функций.

...