6

我做通通過引用這樣的:有沒有更好的方式在Perl中通過引用傳遞?

use strict; 
use warnings; 

sub repl { 
    local *line = \$_[0]; our $line; 
    $line = "new value"; 
} 

sub doRepl { 
    my ($replFunc) = @_; 
    my $foo = "old value"; 
    $replFunc->($foo); 
    print $foo; # prints "new value"; 
} 

doRepl(\&repl); 

是否有這樣做的更清潔的方式?

原型不工作,因爲我正在使用函數引用(相信我,有一個很好的理由使用函數引用)。

我也不想在repl的任何地方使用$_[0],因爲它很醜。

回答

9

你看了看Data::Alias?它允許您使用乾淨的語法創建詞法範圍的別名。

您可以使用它來創建傳遞by-reference語義是這樣的:

use strict; 
use warnings; 

use Data::Alias; 

sub foo { 
    alias my ($arg) = @_; 
    $arg++; 
} 

my $count = 0; 

foo($count); 

print "$count\n"; 

輸出爲1,表明調用foo修改其參數。

+0

不幸的是,我看着文檔的「實施」部分... ack!我猜這個模塊有點像香腸......如果你不知道它們是如何製作的,那麼它會更令人愉快...... :) – JoelFan 2010-03-18 16:22:31

+0

@JoelFan:yup。這是一個「不要在家裏嘗試這個」模塊:) – 2010-03-18 16:37:12

+0

開始「這個模塊不使用源過濾器」,並從那裏下坡... :) – JoelFan 2010-03-18 20:01:30

3

有幾種方法可以做到這一點。顯式傳遞一個標量ref到$foo,或利用Perl的內置傳遞引用語義。

明確提及:

my $foo = "old value"; 
doRepl(\&repl, \$foo); 
print $foo; # prints "new value"; 

sub repl { 
    my $line = shift; 
    $$line = "new value"; 
} 

sub doRepl { 
    my ($replFunc, $foo) = @_; 
    $replFunc->($foo); 
} 

通過引用傳遞:

my $foo = "old value"; 
doRepl(\&repl, $foo); 
print $foo; # prints "new value"; 

sub repl { 
    $_[0] = "new value"; 
} 

sub doRepl { 
    my $replFunc = shift; 
    $replFunc->(@_); 
} 

即使是發燒友通過引用傳遞:

my $foo = "old value"; 
doRepl(\&repl, $foo); 
print $foo; # prints "new value"; 

sub repl { 
    $_[0] = "new value"; 
} 

sub doRepl { 
    my $replFunc = shift; 
    &$replFunc; 
} 

第一個使用正常的perl的硬引用做的工作。

ref方法的第一次傳遞使用了Perl將參數作爲引用傳遞給所有函數的事實。當調用子例程時,@_的元素實際上是參數列表中值的別名。通過改變foo()中的$_[0],您實際上將第一個參數更改爲foo()

第二次通過ref方法使用的事實是,調用& sigil並且沒有parens調用的子實例獲取調用者的@_數組。否則它是相同的。

更新:我只是注意到你想避免$_[0]。如果你願意,你可以在repl中這樣做:

sub repl { 
    for my $line($_[0]) { 
     $line = 'new value'; 
    } 
} 
+0

謝謝...良好的信息,但我想要「隱式」通過參考文獻 – JoelFan 2010-03-17 18:48:49

3

 

sub repl { 
    my $line = \$_[0];  # or: my $line = \shift 
    $$line = "new value"; 
} 
+0

或'我的($行)= \(@_);' – 2010-03-17 18:40:07

+0

@Sinan - 不會猜測會奏效。每天學習新東西。 – mob 2010-03-17 19:28:04

+1

rule參見http://perldoc.perl.org/perlref.html#Making-References「作爲一種特殊情況,'\(@ foo)'返回'@ foo'內容的引用列表,而不是引用到'@ foo'本身。「 – 2010-03-17 19:46:01

0

我不認爲這有什麼錯誤使用local建立在這種情況下別名。

動態範圍當然是一個強大的功能,但只要您意識到副作用(新值在從其範圍調用的函數中可見,如果同一名稱的詞彙在範圍內,本地化......),那麼它對已經溢出的Perl工具箱來說是一個有用的補充。

Perl文檔中有關local的警告的主要原因是爲了防止人們無意中使用它而不是my並緩解從perl4過渡。但是有一些時候local是有用的,這是一個。

使用for來創建您的別名也是一個選項,但我發現明確的語法與local明確的意圖。如果性能受到關注,速度也會更快。

相關問題