Просто ради полноты:
кажется, что всякий раз, когда текстовое представление обновляется слушателем изменения свойства, оно обнаруживает изменение в своем собственном контенте и, таким образом, пытается сохранить его обратно в наблюдаемое запускает цикл, так как вы используете двустороннюю привязку.
blockquote>Проблема может быть решена путем использования односторонней привязки (
@{}
), так как при изменении текста текстовое представление будет запускать своих собственных слушателей и пытаться изменить наблюдаемое, отправляя его в бесконечное число рекурсии.
см. http://perldoc.perl.org/functions/print.html
Обратите внимание, что при хранении ДЕСКРИПТОРОВ ФАЙЛОВ в массиве, или если Вы используете какое-либо другое выражение, более сложное, чем скалярная переменная для получения его, необходимо будет использовать блок, возвращающий значение дескриптора файла вместо этого:...
Так, в Вашем случае Вы использовали бы блок как это:
print { $somehash{$var}{fh} } "foo";
Вышеупомянутые ответы все корректны. Причина, которую они не позволяют полному выражению там, print FH LIST
уже довольно странный синтаксис. Помещать что-либо более сложное там представило бы тонну неоднозначного синтаксиса. Блок удалил ту неоднозначность.
Для наблюдения, куда это безумие приводит к рассмотрите ужас, который является синтаксисом косвенного дополнения.
foo $bar; # Is that foo($bar) or $bar->foo()? Good luck!
Если у Вас есть что-нибудь кроме простого скаляра как Ваш дескриптор файла, необходимо перенести ссылку, содержащую дескриптор файла в фигурных скобках, таким образом, Perl знает, как проанализировать оператор:
print { $somehash{$var}{fh} } $foo;
Часть Лучших практик Perl говорит, чтобы всегда перенести дескрипторы файлов в фигурные скобки просто поэтому, хотя я не получаю это сумасшедшее с нею.
Синтаксис нечетен потому что print
косвенный метод на объекте дескриптора файла:
method_name Object @arguments;
Вы, возможно, видели это в олдскульном CGI.pm. Вот два косвенных вызова метода:
use CGI;
my $cgi_object = new CGI 'cat=Buster&bird=nightengale';
my $value = param $cgi_object 'bird';
print "Indirect value is $value\n";
Это почти хорошо работает (см. ответ Schwern о неоднозначности), как долго как объект находится в простом скаляре. Однако, если я поместил $cgi_object
в хеше я получаю ту же синтаксическую ошибку, с которой Вы добрались print
. Я могу поместить фигурные скобки вокруг доступа хеша, чтобы заставить его удаться. Продолжая предыдущий код:
my %hash;
$hash{animals}{cgi} = $cgi_object;
# $value = param $hash{animals}{cgi} 'cat'; # syntax error
$value = param { $hash{animals}{cgi} } 'cat';
print "Braced value is $value\n";
Это все немного неуклюже, поэтому просто используют нотацию стрелки для всего вместо этого:
my $cgi_object = CGI->new( ... );
$cgi_object->param( ... );
$hash{animals}{cgi}->param( ... );
Можно сделать то же с дескрипторами файлов, хотя необходимо использовать IO:: модуль Дескриптора, чтобы заставить все это удаться:
use IO::Handle;
STDOUT->print( 'Hello World' );
open my( $fh ), ">", $filename or die ...;
$fh->print( ... );
$hash{animals}{fh} = $fh;
$hash{animals}{fh}->print( ... );