2010-08-09 27 views
8

Tôi đọc "Bắt đầu từ Perl" cuốn sách, và nó mang lại cho hai câu lệnh sau đây:Danh sách Phương thức ưu tiên trong Perl

print "Test one: ", 6 > 3 && 3 > 4, "\n"; 
print "Test two: ", 6 > 3 and 3 > 4, "\n"; 

Dòng đầu tiên in gì với một dòng mới, dòng thứ hai in 1 với không có dòng mới.

Tôi đang nhầm lẫn về đầu ra. Theo tác giả, tuyên bố thứ hai cho ra kết quả kỳ lạ vì nó giống như nói:

print ("Test two: ", 6 > 3) and 3 > 4, "\n"; 

Tuy nhiên, tại sao câu đầu tiên không giống nhau? Tôi nghĩ rằng nó có cái gì đó để làm với ưu tiên của in. Các & & có quyền ưu tiên cao hơn so với in, vì vậy nó được đánh giá đầu tiên và sau đó nó được in. Trong khi "và" có ưu tiên thấp hơn so với in, vì vậy 6> 3 sẽ được in, in trả về 1 và sau đó được đánh giá bằng "và". Tuy nhiên điều này không thực sự có ý nghĩa.

Tôi đã đọc tài liệu Perl về cách ưu tiên hoạt động cho các toán tử danh sách, nhưng tôi vẫn không hiểu ví dụ này. Các bạn có thể mổ xẻ hai câu, và cho tôi biết những gì được in trước? Bạn cũng có thể giải thích tài liệu Perl có nghĩa là khi nó đề cập đến các toán tử danh sách là "trái" và "phải không?" Cảm ơn.


Cảm ơn rất nhiều người đã trả lời câu hỏi của bạn. Tôi hiểu nó ngay bây giờ. Tôi đã thực sự làm những gì cjm nói, và nghĩ rằng có những người điều hành danh sách bên trái và bên phải. Vì vậy, bây giờ tôi hiểu ý nghĩa của nó, tôi hiểu toàn bộ sự việc.

+0

mã này in cảnh báo. và thậm chí có cả hành vi của funner trong Devel :: REPL – xenoterracide

+0

@xenoterracide, nó không có ý định là mã Perl tốt. Nó chỉ cố gắng minh họa cách ưu tiên hoạt động. – cjm

+0

@cjm đúng ... mặc dù hành vi của re.pl có vẻ sai, đủ để tôi gửi một lỗi lên đó. chúng ta sẽ thấy điều gì xảy ra. – xenoterracide

Trả lời

12

Được rồi, đối với người mới bắt đầu: các toán tử danh sách nằm trong số những ưu tiên thấp nhất trong perl, nhưng chỉ ở bên phải của chúng. Bạn hỏi điều đó có nghĩa là: tốt, hãy làm cho nó đơn giản. Giả sử có một danh sách gọi là foo. Nó không quan trọng những gì nó làm, nhưng nó ở đó. Bạn có thể dễ dàng tạo ra một điều như vậy với sub foo { map 10 * $_, @_ } trả về mỗi đối số của nó nhân với mười. Đó ra khỏi con đường:

print 1, 2, 3; tương đương với print(1, 2, 3);
print foo 1, 2, 3; tương đương với print(foo(1, 2, 3));
print 1, foo 2, 3; tương đương với print(1, foo(2, 3));

Chúng ta có thể thấy rằng foo gobbles lên nhiều như nó có thể ở bên phải - chỉ có kết thúc của tuyên bố (cho đến nay ...) có thể ngăn chặn nó. Nếu chúng tôi viết @array = (1, foo 2, 3); sẽ tương đương với @array = (1, foo(2, 3)); vì tất nhiên kết thúc dấu ngoặc đơn xung quanh vẫn được áp dụng.

Vì dấu phẩy cũng rất ưu tiên (chỉ ở trên "Toán tử danh sách (bên phải)"), chúng tôi cũng có thể đặt khá nhiều loại biểu thức chúng tôi muốn vào đối số cho danh sách - đây chỉ là cách của perl đảm bảo chúng tôi không phải thêm dấu ngoặc đơn hầu hết thời gian. Toán học, toán tử bitwise, so sánh, thậm chí các trận đấu regex có ưu tiên cao hơn.

Những điều duy nhất mà làm có ưu tiên thấp hơn là những từ nối vần-out logic and, or, xor, và not. Vì vậy, nếu chúng ta viết

foo 1, 2, 3 and 4; 

đó có nghĩa là (foo(1, 2, 3) and 4) - biện minh cho khả foo dừng ở phía bên trái của and.Điều này có vẻ ngớ ngẩn trong một ví dụ giả tạo, vì vậy hãy biến nó thành một perl thành ngữ phổ biến:

open $fh, '<', $filename or die "$! opening $filename"; 

tương đương với

(open($fh, '<', $filename) or die("$! opening $filename")); 

mà thực sự là chính xác tương đương với (và biên dịch để)

die "$! opening $filename" unless open $fh, '<', $filename; 

sử dụng biểu mẫu sửa đổi tuyên bố là unless (không phải là toán tử nào cả, chỉ được phép một lần cho mỗi câu lệnh và chỉ xuất hiện ở cuối câu lệnh, vì vậy nó không ' t thực sự tham gia vào ưu tiên ở tất cả, nhưng bạn có thể xem nó như là "thấp hơn thấp hơn" ưu tiên còn lại). Vì vậy, dù sao, quay trở lại mẫu mã ban đầu của bạn - các đối số cho print kết thúc bên trái của and và bên phải của and là một biểu thức dấu phẩy hoàn toàn riêng biệt - không có gì cả vì nó chỉ là một vài hằng số 3 > 4"\n" được đánh giá trong ngữ cảnh trống.

+1

++: Giải thích sao! – Zaid

8

Sau đây là cách những tuyên bố sẽ xem xét với dấu ngoặc đơn đầy đủ:

print("Test one: ", ((6 > 3) && (3 > 4)), "\n"); 
print("Test two: ", (6 > 3)) and ((3 > 4), "\n"); 

> có ưu tiên cao nhất, sau đó &&, sau đó ,, sau đó print, sau đó and.

6 > 3 đánh giá là 1. 3 > 4 đánh giá sai, trong Perl là một giá trị đặc biệt bằng 0 trong ngữ cảnh số nhưng chuỗi trống trong ngữ cảnh chuỗi (như ở đây). Vì vậy, ((6 > 3) && (3 > 4)) mang lại chuỗi rỗng.

Do đó, câu lệnh đầu tiên chuyển 3 đối số đến print: "Test one: ", chuỗi trống và dòng mới. Nó in từng đối số theo thứ tự.

Câu lệnh thứ hai chỉ chuyển 2 đối số đến print: "Test two: "1. Dòng mới không được in vì nó chưa bao giờ được chuyển đến print.

Tôi không chắc chắn cách giải thích "leftward" và "rightward" tốt hơn the docs. Nhưng có thể điều khiến bạn khó hiểu là bạn đang nghĩ rằng có những "ops danh sách bên trái" và "ops danh sách bên phải". Đó không phải là ý nghĩa của nó. Nó đang cố gắng nói rằng mọi thứ ở phía bên phải của toán tử danh sách được hiểu là các đối số cho toán tử đó (trừ khi bạn nhấn một trong những toán tử Boolean có mức ưu tiên rất thấp như and). Nhưng mọi thứ ở phía bên trái của toán tử danh sách không được liên kết với toán tử danh sách đó.

+0

@hobbs: Theo cách nào thì nó không đúng? musikk và tôi nói điều tương tự, ngoại trừ tôi đã sử dụng một số parens thêm (và tuyên bố của anh ta bây giờ rút lại rằng '3> 4' là' undef'). Đầu ra của 'perl -MO = Deparse, -p' giống hệt với các câu lệnh gốc so với các phiên bản được lồng đầy đủ của tôi. – cjm

+0

Tôi xin lỗi, có vẻ như tôi đã đọc sai. – hobbs

+0

Tính năng này hoạt động như thế nào trong trường hợp các toán tử kiểm tra tệp? Ví dụ: sử dụng ['Test :: More'] (https://metacpan.org/pod/Test::More) Tôi đã viết bài kiểm tra này 'ok (not -e $ fn,' file không tồn tại ')' ngược lại với những gì tôi mong đợi .. –

4

Giống như bạn nói, ngoại trừ phần "điều này không có ý nghĩa".

Đầu tiên là

print "Test one: ", (6 > 3 && 3 > 4), "\n"; 

và thứ hai

(print "Test two: ", 6 > 3) and (3 > 4, "\n"); 

Nếu bạn bật cảnh báo (use warnings), bạn nhận được cảnh báo Useless use of a constant in void context vì phía bên phải của and đánh giá vào một danh sách với các yếu tố false và dòng mới nhưng không bao giờ được sử dụng.

chỉnh sửa: Đã sửa yêu cầu 3> 4 của bạn là undef. Sai không phải là undef. Nó được xác định và in không có gì.

Các vấn đề liên quan