2011-06-20 48 views
2

如果我可以用shift,push和其他內置子例程的方式使用子例程,它會使我的腳本更容易些:它們都可以直接更改變量傳遞給它,而無需返回更改。直接將參數改爲子例程

當我嘗試這樣做時,變量在某個點被複制,而我似乎只是簡單地更改副本。我明白,這將是很好的參考,但它甚至發生在陣列和散列,我覺得我只是簡單地將我正在處理的變量傳遞給子,以便可以完成更多的工作:

@it = (10,11); 
changeThis(@it); 
print join(" ", @it),"\n"; #prints 10 11 but not 12 

sub changeThis{ 
    $_[2] = 12; 
} 

有沒有辦法做到這一點?我知道這不是最佳做法,但在我看來,這將非常方便。

+0

改變爲清楚起見。乾杯! – MattLBeck

回答

5

問題是,子調用將變量擴展爲一個值列表,並將其傳遞給子例程。即一個副本被傳遞,而不是變量本身。你的子呼叫等於:

changeThis(11, 12); 

如果你想改變原來的數組,傳遞而不是一個參考:

use strict; 
use warnings; 

my @it = (10,11); 
changeThis(\@it); 
print join(" ", @it),"\n"; 

sub changeThis{ 
    my $array = shift; 
    $$array[2] = 12; 
} 

此外,@_[2]會給你警告:

Scalar value @_[2] better written as $_[2] 

如果你use warnings,你當然應該這樣做。除非你確切地知道你在做什麼,否則沒有充分的理由不打開警告和嚴格的規定。

+0

哦,我現在看到問題了!但是,在這種情況下,內置函數需要解除引用的變量會有點矛盾。 – MattLBeck

+0

@kikumbob你指的是哪些內置函數? – TLP

+0

移位,不移位,推送,彈出等。另外,當然我使用警告!我給的代碼是一個片段,我沒有打擾編譯器(我會下次...):) – MattLBeck

10

這就是原型是什麼:

#!/usr/bin/perl 

use strict; 
use warnings; 

sub changeThis(\@);  # the argument will be seen as an array ref (prototype must come before the call!) 

my @it = (10,11); 
changeThis @it;   # even when called with an array 
print join(" ", @it),"\n"; #prints 10 11 12 

sub changeThis(\@) 
    { my($ar)= @_; $ar->[2]= 12; } 

更多信息請參見http://perldoc.perl.org/perlsub.html#Prototypes

雖然這不是一個真正流行的方法,但傳遞實際的數組引用可能是一個更好的選擇,但涉及的魔術較少。

+0

+1用於回答我的回答中評論中OP的問題的部分內容。併爲我教授新的東西。 :) – TLP

+0

事實上,原始參數是別名是有用的,原型OTOH ......它們的創建完全是爲了模仿Perl內置的語法,但很少有人真正使用它們。 HTTPS://www.socialtext。淨/ perl5 /原型也有一些更多的信息和鏈接 – mirod

+0

是的,這回答了我的問題的另一半。它是一個恥辱,我只有足夠的墨水爲一個滴答聲:-( – MattLBeck

2

正如前面的答案所示,應該使用傳遞給子例程的引用。 此外,如果你想閱讀線槽documentation for Prototypes

sub changeThis(\@); 

@it = (10,11); 
changeThis @it; 
print join(" ", @it),"\n"; #prints 10 11 12 

sub changeThis(\@){ 
    $_[0][2] = 12; 
} 

你也可以使用隱式引用(請注意,您可能已在第一次調用之前預先聲明你的潛艇或將子定義在上面。)

相關問題