2012-02-06 38 views
7

在Perl中,是否有任何理由將單個變量封裝在雙引號(無級聯)中?perl在雙引號中封裝單個變量

我經常在我的工作程序的源(writen 10年前的人們,在這裏不工作了)找到這個:

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

據我所知,沒有任何理由去做這個。當我在舊腳本中工作時,我通常會刪除引號,以便編輯器將它們作爲變量而不是字符串。

我覺得他們在某個地方看到了這個地方,並且不知道它爲什麼會這樣。我錯過了什麼嗎?

謝謝。

+2

這是一個很好的問題,因爲答案在這裏只顯示當重新分解舊代碼,你應該如何小心是 - 有可能是一個很好的理由,起初看起來像不好的風格。 – tangent 2012-02-06 20:21:25

回答

7

所有這些都明確地將變量串聯起來。在99.9%的情況下,這是一種新手的錯誤。

有些事情也可能發生這種調用風格的副作用:

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

這裏,字串創建副本,並通過了給子程序,繞過Perl的通過引用傳遞語義。通常認爲這是不好的方式來調用變量,所以你可能沒問題。

您也可以在此處將對象或其他值字符串化。例如,將undef串化爲空字符串。對象可以指定在字符串化時運行的任意代碼。有可能具有不同數值和字符串值的雙值標量。這是一種指定您想要字符串表單的方法。

還有一件可能會發生的深刻的鬼怪事情。如果您正在使用XS代碼來查看設置在函數的標量參數上的標誌,則對標量進行字符串化是一種直接的方式,對perl說:「給我一個很好的乾淨的新字符串值」沒有數字標誌。

我相信99.9%的規則還有其他奇怪的例外。這些是少數。在刪除引號之前,花點時間檢查一下這個奇怪的垃圾。如果確實發生了合法用法,請添加一條評論,將引用標識爲可行的雜湊,並給出其存在的理由。

+0

Re「如果您正在處理XS代碼,該代碼查看在函數的標量參數上設置的標誌」,我之前展示了一個Pure Perl示例。任何使用'ref()'的東西就足夠了。 – ikegami 2012-02-06 18:54:27

6

在這種情況下,雙引號是不必要的。此外,使用它們效率低下,因爲這會導致原始字符串被複制。

但是,有時您可能想要使用此樣式來「串化」一個對象。例如,URI ojects支持字串:

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

如果警告尚未啓用,它也會悄悄地將'undef'變成空字符串,不是嗎?儘管如此,我不會說這是一個有效的用途,但我可能不會認爲任何事情都沒有被警告起來有效。 – 2012-02-06 09:16:28

+0

@mu太短:是的,'undef'會變成''「''(不管是否啓用警告) – 2012-02-06 09:26:30

+0

但它不會安靜地發出警告,你會得到」未初始化的串聯值「 , – 2012-02-06 09:28:27

6

我不知道爲什麼,但它是常用的初來乍到的Perl的模式。這通常是浪費(因爲它在你發佈的片段中),但我可以考慮兩種用途。


它具有創建一個與原始值相同的新字符串的效果,這在非常罕見的情況下可能會有用。

在下面的示例中,顯式複製是爲了保護$ x免受子修改,因爲子修改了它的參數。

$ 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 

憑藉創建字符串的副本,它stringifies對象。這在處理代碼時根據參數是否爲參考來改變其行爲可能很有用。

在下面的示例中,完成了顯式字符串化,因爲require以與字符串不同的方式處理@INC中的引用。

$ 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

第一種情況可以被描述爲「解決方法@_具有明確副本的別名」。我會建議在做這些事情的代碼中添加註釋。 – dolmen 2012-02-10 10:41:00

+0

@dolmen,添加了示例的說明。 – ikegami 2012-02-10 19:51:15

0

我的理論一直是,人們從其他語言習慣了壞習慣。這並不是說他們在想「我會一直用雙引號」,但他們只是沒有想到!

我會誠實地說,我曾經陷入這個陷阱,因爲我來自Java的Perl,所以肌肉記憶在那裏,只是不停地開火。

PerlCritic終於讓我擺脫了這種習慣!

這絕對會讓你的代碼更有效率,但是如果你沒有想到你是否想插入你的字符串,你很可能會犯一些愚蠢的錯誤,所以我會進一步說它是危險的。

2

在你的情況下引號是完全無用的。我們甚至可以說這是錯誤的,因爲這不像其他人寫的那樣是慣用的。

但是引用一個變量有時可能是必要的:這會明確地觸發變量值的串化。如果值是雙重變量,或者如果它們是具有overload ed字符串的祝福值,則字符串化可能會給某些值提供不同的結果。

這裏是雙瓦爾一個例子:

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

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

輸出:

1 
2