2010-03-19 35 views
6

Trong Perl, khi bạn có cấu trúc dữ liệu lồng nhau, bạn có thể bỏ qua các mũi tên không tham chiếu đến 2d và nhiều cấp độ lồng nhau hơn. Nói cách khác, hai cú pháp sau đây là giống hệt nhau:Mũi tên dereferencing lồng nhau trong Perl: để bỏ qua hoặc không bỏ qua?

my $hash_ref = { 1 => [ 11, 12, 13 ], 3 => [31, 32] }; 

my $elem1 = $hash_ref->{1}->[1]; 
my $elem2 = $hash_ref->{1}[1]; # exactly the same as above 

Bây giờ, câu hỏi của tôi là, là có một lý do chính đáng để lựa chọn một phong cách so với khác?

Nó có vẻ là một xương phổ biến của tranh luận phong cách (Chỉ cần trên SO, tôi vô tình va vào thisthis trong không gian 5 phút).

Cho đến nay, hầu như không ai trong số các nghi phạm thông thường nói bất cứ điều gì dứt khoát:

  • perldoc chỉ nói "bạn được tự do để bỏ qua con trỏ dereferencing mũi tên".
  • "Thực tiễn tốt nhất Perl" của Conway nói "bất cứ khi nào có thể, dereference với mũi tên", nhưng nó dường như chỉ áp dụng cho bối cảnh dereferencing tham chiếu chính, chứ không phải mũi tên tùy chọn trên mức 2d của cấu trúc dữ liệu lồng nhau.
  • "Mastering Perl cho Bioinfirmatics" tác giả James Tisdall không dành ưu tiên rất rắn hoặc:

    "Người đọc bén nhạy có thể có nhận thấy rằng chúng ta dường như được bỏ qua khai thác mũi tên giữa mảng (Sau khi tất cả, đây là mảng vô danh của mảng ẩn danh của mảng ẩn danh, v.v., do đó, không được viết [$ array -> [$ i] -> [$ j] -> [$ k]?) Perl cho phép điều này, chỉ có toán tử mũi tên giữa tên biến và yêu cầu chỉ số mảng đầu tiên. Nó làm cho mọi thứ dễ dàng hơn trên mắt và giúp tránh hội chứng ống cổ tay. Mặt khác, trên , bạn có thể muốn giữ các mũi tên dereferencing tại chỗ, để làm rõ rằng bạn đang xử lý các tham chiếu . sự lựa chọn của bạn."

  • CẬP NHẬT "Intermediate Perl", theo đồng tác giả của nó brian d Foy, khuyên bạn bỏ qua các mũi tên. Xem câu trả lời đầy đủ brian của bên dưới.

Cá nhân, tôi ở bên cạnh "luôn đặt mũi tên vào, vì nó dễ đọc hơn và rõ ràng chúng đang đối phó với một tham chiếu".

CẬP NHẬT Để cụ thể hơn: khả năng đọc lại, trong trường hợp biểu thức đa lồng nhau ở đâu e subscript chính là biểu thức, các mũi tên giúp "biểu thị trực quan" các biểu thức bằng cách rõ ràng hơn là tách các bảng con khỏi nhau.

+0

brian - hệ thống không cho tôi biết bạn đã cập nhật câu trả lời, xin lỗi vì đã chú ý muộn. – DVK

Trả lời

13

Trừ khi bạn thực sự thích gõ hoặc đường quá dài, không sử dụng các mũi tên khi bạn không cần chúng. Các bản đăng ký bên cạnh các bản đăng ký ngụ ý các tham chiếu, do đó người lập trình có thẩm quyền không cần thêm manh mối để tìm ra điều đó.

Tôi không đồng ý rằng nó dễ đọc hơn khi có thêm mũi tên.Nó chắc chắn không phải là độc đáo để họ di chuyển những phần thú vị của thuật ngữ xa nhau.

Trong Intermediate Perl, nơi chúng tôi thực sự dạy tài liệu tham khảo, chúng tôi yêu cầu bạn bỏ qua các mũi tên không cần thiết.

Ngoài ra, hãy nhớ rằng không có điều gì là "khả năng đọc". Chỉ có những gì bạn (và những người khác) đã đào tạo đôi mắt của bạn để nhận ra là các mẫu. Bạn không đọc mọi thứ theo từng ký tự, sau đó tìm ra ý nghĩa của chúng. Bạn thấy các nhóm thứ mà bạn đã thấy trước đây và nhận ra chúng. Ở cấp độ cú pháp cơ sở mà bạn đang nói đến, "khả năng đọc" của bạn chỉ là khả năng nhận ra các mẫu của bạn. Nó dễ dàng hơn để nhận ra các mẫu bạn càng sử dụng nó, do đó, nó không đáng ngạc nhiên rằng những gì bạn làm bây giờ là "dễ đọc" cho bạn. Phong cách mới có vẻ lạ lúc đầu, nhưng cuối cùng trở nên dễ nhận biết hơn, và do đó dễ đọc hơn.

Ví dụ bạn đưa ra trong nhận xét của bạn không khó đọc vì thiếu các mũi tên. Nó vẫn khó đọc có mũi tên:

$expr1->[$sub1{$x}]{$sub2[$y]-33*$x3}{24456+myFunct($abc)} 
$expr1->[$sub1{$x}]->{$sub2[$y]-33*$x3}->{24456+myFunct($abc)} 

tôi viết rằng loại mã như thế này, sử dụng các loại tên biến để nhắc nhở các coder tiếp theo về các loại thùng chứa mỗi cấp là:

my $index = $sub1{$x}; 
my $key1 = $sub2[$y]-33*$x3; 
my $key2 = 24456+myFunct($abc); 

$expr1->[ $index ]{ $key1 }{ $key2 }; 

Để làm cho điều đó tốt hơn, hãy ẩn các chi tiết trong một chương trình con (đó là những gì chúng có trong :) vì vậy bạn không bao giờ phải chơi với mớ hỗn độn của cấu trúc dữ liệu một cách trực tiếp. Điều này dễ đọc hơn mà bất kỳ ai trong số họ:

my $value = get_value($index, $key1, $key2); 

    my $value = get_value(
    $sub1{$x}, 
    $sub2[$y]-33*$x3, 
    24456+myFunct($abc) 
    ); 
+0

Mặc dù brian không cần phiếu bầu của tôi, nhưng tôi thực sự thích phần "thú vị của thuật ngữ". – Axeman

+0

brian - bất kỳ đầu vào trên quan điểm của tôi được thực hiện cho Jefromi? Ví dụ. khoảng cách thêm giữa các bảng con giúp "trực quan mã hóa" chúng - điều này rất quan trọng khi viết $ a -> [2] {c} nhưng nhiều hơn với biểu thức liên quan nhiều hơn như "$ expr1 -> [$ sub1 {$ x}] {$ sub2 [$ y] -33 * $ x3} {24456 + myFunct ($ abc)} "(KHÔNG phải mã thực sự của tôi!) – DVK

+0

PS Hoàn toàn không liên quan - nhưng bạn có câu trả lời nào cho câu hỏi Meta này không? http://meta.stackexchange.com/questions/42797/randal-schwartz-on-so-but-not-in-perl – DVK

1

Tôi luôn viết tất cả các mũi tên. Tôi đồng ý với bạn, họ tách biệt tốt hơn các bảng con khác nhau. Thêm vào đó, tôi sử dụng dấu ngoặc nhọn cho biểu thức chính quy, do đó, đối với tôi, {foo}{bar} là một sự thay thế: s{foo}{bar} nổi bật hơn từ $s->{foo}->{bar} so với số $s->{foo}{bar}.

Tôi không nghĩ rằng đó là một vấn đề lớn, mặc dù đọc mã mà bỏ qua các mũi tên thêm không phải là một vấn đề (như trái ngược với bất kỳ thụt đầu dòng đó không phải là một tôi sử dụng; -)

2

Kể từ khi -> mũi tên không được sử dụng tùy chọn cho các cuộc gọi phương thức, tôi thích chỉ sử dụng nó để gọi mã. Vì vậy, tôi sẽ sử dụng như sau:

$object->method; 
$coderef->(); 
$$dispatch{name}->(); 

$$arrayref[1]; 
$$arrayref[1][5]; 
@$arrayref[1 .. 5]; 
@$arrayref; 
$$hashref{foo}; 
$$hashref{foo}{bar}; 
@$hashref{qw/foo bar/}; 
%$hashref; 

Hai sigils trở lại trở lại lúc nào cũng có nghĩa là một dereference, và cơ cấu vẫn ổn định trên tất cả các hình thức dereferencing (vô hướng, lát, tất cả).

Nó cũng giữ tất cả các phần của biến "cùng nhau" mà tôi tìm thấy dễ đọc hơn và ngắn hơn :)

+0

Nhưng không phải tất cả các tham chiếu đều có hai sigils back-to-back :) –

+1

Chính xác, và vì có lựa chọn cho dereferencing, và không cho các cuộc gọi phương thức ... "Tôi nghĩ rằng ẩn dụ hình ảnh là rất quan trọng. Làm thế nào nó trông. Những thứ khác nhau nên trông khác nhau. trông tương tự." ~ Larry Wall. Mã gọi là rất khác với các hình thức dereferencing khác. –

+2

Hãy xem $ {$ hash {a}} {b} và $$ hash {a} {b} và nhờ Perler thiếu kinh nghiệm để cho bạn biết lý do tại sao những thứ đó khác nhau. Nó dễ dàng hơn nhiều để làm cho những thứ đó trông khác với mũi tên hàng đầu. Như Larry đã nói, những thứ khác nhau sẽ khác nhau. –