2012-02-06 27 views
7

Trong Perl, có lý do nào để đóng gói một biến duy nhất trong dấu nháy kép (không nối) không?perl đóng gói biến duy nhất trong ngoặc kép

tôi thường tìm thấy điều này trong nguồn của chương trình tôi đang làm việc trên (bằng văn bản cách đây 10 năm bởi những người mà không làm việc ở đây nữa):

my $sql_host = "something"; 
my $sql_user = "somethingelse"; 

# a few lines down 
my $db = sub_for_sql_conection("$sql_host", "$sql_user", "$sql_pass", "$sql_db"); 

Theo như tôi biết không có lý do để làm điều này. Khi tôi làm việc trong một tập lệnh cũ, tôi thường xóa dấu ngoặc kép để trình chỉnh sửa của tôi tô màu chúng thành các biến không phải là chuỗi.

Tôi nghĩ họ đã thấy điều này ở đâu đó và sao chép phong cách mà không hiểu tại sao lại như vậy. Tui bỏ lỡ điều gì vậy ?

Cảm ơn bạn.

+2

Đây là một câu hỏi hay vì câu trả lời ở đây hiển thị như thế nào cẩn thận bạn sẽ có khi lại phân tách mã cũ - chỉ có thể là một lý do tốt cho một cái gì đó mà lúc đầu xuất hiện như phong cách xấu. – tangent

Trả lời

7

Tất cả điều này làm rõ ràng là xâu chuỗi các biến. Trong 99,9% trường hợp, nó là một lỗi newbie của một số loại.

Có những điều có thể xảy ra như một tác dụng phụ của phong cách gọi này:

my $foo = "1234"; 
sub bar { $_[0] =~ s/2/two/ } 
print "Foo is $foo\n"; 
bar("$foo"); 
print "Foo is $foo\n"; 
bar($foo); 
print "Foo is $foo\n"; 

Ở đây, stringification tạo một bản sao và qua đó đến chương trình con, phá vỡ đường chuyền Perl bằng cách ngữ nghĩa tham khảo. Nó thường được coi là cách cư xử xấu để munge gọi biến, vì vậy bạn có lẽ không sao.

Bạn cũng có thể xâu chuỗi một đối tượng hoặc giá trị khác tại đây. Ví dụ: undef xâu thành chuỗi rỗng. Các đối tượng có thể chỉ định mã tùy ý để chạy khi được xâu chuỗi. Có thể có các vô hướng có giá trị kép có giá trị số và chuỗi riêng biệt. Đây là một cách để xác định rằng bạn muốn biểu mẫu chuỗi.

Ngoài ra còn có một điều ma quái sâu có thể xảy ra. Nếu bạn đang làm việc với mã XS xem xét các cờ được đặt trên các đối số vô hướng cho một hàm, việc xâu chuỗi vô hướng là một cách thẳng tiến để nói với perl, "Làm cho tôi một giá trị chuỗi mới sạch đẹp" chỉ với các cờ xâu chuỗi và không có cờ số.

Tôi chắc chắn có các ngoại lệ lẻ khác với quy tắc 99,9%. Đây là một vài. Trước khi loại bỏ các dấu ngoặc kép, hãy dành một giây để kiểm tra cái crap kỳ lạ như thế này. Nếu bạn xảy ra khi sử dụng hợp pháp, vui lòng thêm nhận xét xác định các dấu ngoặc kép là một kludge khả thi và đưa ra lý do cho sự tồn tại của chúng.

+0

Re "Nếu bạn đang làm việc với mã XS nhìn vào các cờ được đặt trên đối số vô hướng cho một hàm", trước đây tôi đã hiển thị một ví dụ về Perl thuần túy. Bất cứ điều gì sử dụng 'ref()' sẽ là đủ. – ikegami

6

Trong trường hợp này, dấu ngoặc kép không cần thiết. Hơn nữa, việc sử dụng chúng không hiệu quả vì điều này làm cho các chuỗi gốc được sao chép.

Tuy nhiên, đôi khi bạn có thể muốn sử dụng kiểu này để "xâu chuỗi" một đối tượng. Ví dụ, URI ojects hỗ trợ stringification:

my $uri = URI->new("http://www.perl.com"); 
my $str = "$uri"; 
+0

Nó cũng sẽ lặng lẽ biến một 'undef' thành một chuỗi rỗng nếu cảnh báo chưa được kích hoạt, phải không? Tôi sẽ không gọi đó là một sử dụng hợp lệ mặc dù, tôi có lẽ sẽ không xem xét bất cứ điều gì mà không có cảnh báo cranked lên được hợp lệ. –

+0

@mu quá ngắn: có, 'undef' sẽ trở thành' "" '(bất kể cảnh báo đã được bật) –

+0

Nhưng nó sẽ không đi lặng lẽ với cảnh báo, bạn sẽ nhận được" uninitialized value in concatenation "khiếu nại . –

6

Tôi không biết tại sao, nhưng đó là một mô hình thường được sử dụng bởi những người mới đến Perl. Nó thường là một sự lãng phí (vì nó nằm trong đoạn trích mà bạn đăng), nhưng tôi có thể nghĩ đến hai cách sử dụng.


Nó có tác dụng tạo chuỗi mới có cùng giá trị như bản gốc và có thể hữu ích trong những trường hợp rất hiếm.

Trong ví dụ sau, một bản sao rõ ràng được thực hiện để bảo vệ $ x khỏi sửa đổi bởi phụ vì phụ sửa đổi đối số của nó.

$ perl -E' 
    sub f { $_[0] =~ tr/a/A/; say $_[0]; } 
    my $x = "abc"; 
    f($x); 
    say $x; 
' 
Abc 
Abc 

$ perl -E' 
    sub f { $_[0] =~ tr/a/A/; say $_[0]; } 
    my $x = "abc"; 
    f("$x"); 
    say $x; 
' 
Abc 
abc 

Nhờ tạo ra một bản sao của chuỗi, nó stringifies đối tượng. Điều này có thể hữu ích khi xử lý mã làm thay đổi hành vi của nó dựa trên việc đối số của nó có phải là tham chiếu hay không.

Trong ví dụ sau, việc xâu chuỗi rõ ràng được thực hiện vì require xử lý các tham chiếu trong @INC khác với chuỗi.

$ perl -MPath::Class=file -E' 
    BEGIN { $lib = file($0)->dir; } 
    use lib $lib; 
    use DBI; 
    say "ok"; 
' 
Can't locate object method "INC" via package "Path::Class::Dir" at -e line 4. 
BEGIN failed--compilation aborted at -e line 4. 

$ perl -MPath::Class=file -E' 
    BEGIN { $lib = file($0)->dir; } 
    use lib "$lib"; 
    use DBI; 
    say "ok"; 
' 
ok 
+0

Trường hợp đầu tiên có thể được mô tả là "workaround @_ aliasing với bản sao rõ ràng". Tôi sẽ khuyên bạn nên thêm ý kiến ​​trong mã mà làm những việc như vậy. – dolmen

+0

@dolmen, Đã thêm mô tả về các ví dụ. – ikegami

0

Lý thuyết của tôi luôn là mọi người đến từ các ngôn ngữ khác có thói quen xấu. Nó không phải là họ đang nghĩ rằng "Tôi sẽ sử dụng dấu nháy kép tất cả các thời gian", nhưng họ chỉ không suy nghĩ!

Tôi sẽ trung thực và nói rằng tôi từng rơi vào bẫy này bởi vì tôi đã đến Perl từ Java, do đó bộ nhớ cơ đã ở đó và chỉ tiếp tục bắn.

PerlCritic cuối cùng đã giúp tôi thoát khỏi thói quen! Nó chắc chắn làm cho mã của bạn hiệu quả hơn, nhưng nếu bạn không suy nghĩ về việc bạn có muốn các chuỗi của bạn nội suy hay không, bạn rất có thể mắc sai lầm ngớ ngẩn, vì vậy tôi sẽ đi xa hơn và nói rằng nó nguy hiểm.

2

Trong báo giá trường hợp của bạn hoàn toàn vô dụng. Chúng tôi thậm chí có thể nói rằng điều đó là sai bởi vì điều này không phải là thành ngữ, như những người khác đã viết.

Tuy nhiên, việc trích dẫn biến có thể đôi khi cần thiết: điều này kích hoạt một cách rõ ràng việc xâu chuỗi giá trị của biến. Việc xâu chuỗi có thể cho kết quả khác nhau đối với một số giá trị nếu các giá trị là các vars kép hoặc nếu chúng là các giá trị may mắn với overload xâu chuỗi hóa.

Dưới đây là một ví dụ với vars kép:

use 5.010; 
use strict; 
use Scalar::Util 'dualvar'; 

my $x = dualvar 1, "2"; 
say 0+$x; 
say 0+"$x"; 

Output:

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