2009-02-12 31 views
8

Tôi có một dòng mã dọc theo dòng:

print $somehash{$var}{fh} "foo"; 

Các băm chứa filehandle một vài cấp độ xuống. Lỗi này là:

String found where operator expected at test.pl line 10, near "} "foo"" 

tôi có thể sửa chữa nó bằng cách làm này:

my $fh = $somehash{$var}{fh}; 
print $fh "foo"; 

... nhưng là có một lớp lót?

+0

Bạn có thể "nói" bất cứ điều gì bạn muốn. Nó nhận được nó để làm việc đó là khôn lanh :) –

Trả lời

23

thấy http://perldoc.perl.org/functions/print.html

Lưu ý rằng nếu bạn đang lưu trữ FILEHANDLEs trong một mảng, hoặc nếu bạn sử dụng bất kỳ biểu hiện khác hơn phức tạp hơn một biến vô hướng để lấy nó, bạn sẽ phải sử dụng khối trả lại giá trị tệp handhandle thay thế: ...

Vì vậy, trong cas của bạn e, bạn sẽ sử dụng một khối như thế này:

print { $somehash{$var}{fh} } "foo"; 
+2

câu trả lời tuyệt vời, và chỉ để làm cho nó cụ thể: in {$ somehash {$ var} {fh}} "foo"; – andy

+0

Điểm tốt @andy, tôi đã chỉnh sửa câu trả lời để bao gồm dòng mã đó. Các chỉnh sửa được chào đón ở đây, hãy cho phép chỉnh sửa lần sau. – Flimm

10

Nếu bạn có bất cứ điều gì khác hơn là một đại lượng vô hướng đơn giản như filehandle của bạn, bạn cần phải quấn tham khảo giữ filehandle trong dấu ngoặc để Perl biết làm thế nào để phân tích báo cáo kết quả:

print { $somehash{$var}{fh} } $foo; 

Một phần của Perl Thực tiễn tốt nhất nói luôn quấn filehandles trong dấu ngoặc chỉ vì lý do này, mặc dù tôi không có được điều đó hấp dẫn với nó.

Cú pháp là số lẻ vì print là một phương pháp gián tiếp vào một đối tượng filehandle:

method_name Object @arguments; 

Bạn có thể thấy điều này trong trường học cũ CGI.pm. Dưới đây là hai phương pháp gián tiếp cuộc gọi:

use CGI; 

my $cgi_object = new CGI 'cat=Buster&bird=nightengale'; 

my $value = param $cgi_object 'bird'; 

print "Indirect value is $value\n"; 

Đó gần như hoạt động tốt (xem Schwern's answer about the ambiguity) miễn là các đối tượng nằm trong một vô hướng đơn giản. Tuy nhiên, nếu tôi đặt $cgi_object trong một băm, tôi nhận được cùng một lỗi cú pháp bạn nhận được với print. Tôi có thể đặt niềng răng xung quanh truy cập băm để làm cho nó hoạt động. Tiếp tục với mã theo thời gian:

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"; 

Đó là tất cả một chút thời gian vì vậy chỉ cần sử dụng các ký hiệu mũi tên cho tất cả mọi thứ thay vì:

my $cgi_object = CGI->new(...); 
$cgi_object->param(...); 

$hash{animals}{cgi}->param(...); 

Bạn có thể làm tương tự với filehandles, mặc dù bạn phải sử dụng IO::Handle mô-đun để làm cho tất cả hoạt động:

use IO::Handle; 

STDOUT->print('Hello World'); 

open my($fh), ">", $filename or die ...; 
$fh->print(...); 

$hash{animals}{fh} = $fh; 

$hash{animals}{fh}->print(...); 
5

Các câu trả lời ở trên đều chính xác. Lý do họ không cho phép một biểu hiện đầy đủ trong đó là print FH LIST đã là cú pháp khá kỳ lạ. Để đặt bất cứ điều gì phức tạp hơn trong đó sẽ giới thiệu một tấn cú pháp mơ hồ. Khối đã loại bỏ sự mơ hồ đó.

Để xem sự điên rồ này dẫn đến đâu, hãy xem xét sự kinh dị đó là cú pháp đối tượng gián tiếp.

foo $bar; # Is that foo($bar) or $bar->foo()? Good luck! 
Các vấn đề liên quan