2015-03-30 62 views
0

我試圖將參數傳遞給perl子例程,並且無論出於何種原因,子例程中的參數都是空的。Perl將參數傳遞給子例程不起作用

... 
... 
... 
print "Passing arguments $a, $b, $c, $d \n"; 
beforeEnd($a, %b, $c, $d); 

sub beforeEnd() { 
    my ($a, %b, $c, $d) = @_; 
    print "a is $a, b is $b, c is $c, d is $d \n"; 
} 

打印語句的輸出給了我一個想法,即某些錯誤。奇怪的部分?前兩個參數正確傳遞。

> Passing arguments 1, (1,2,3), 2, 3 
> a is 1, b is (1,2,3), c is , d is 

任何幫助將不勝感激。

+0

您正在傳遞'%b',但是正在打印'$ b'。 – Barmar 2015-03-30 19:22:08

+0

賦值中的列表變量將接收函數的所有其餘參數。 – Barmar 2015-03-30 19:23:12

+0

如果要傳遞列表而不將其作爲單獨的參數傳播出去,則應該使用數組引用。 – Barmar 2015-03-30 19:24:37

回答

2

因爲當你將參數傳入或傳出子程序時,任何散列和數組都被平坦地砸碎。

您正在分配到%b這將吞噬任何參數。

#!/usr/bin/perl 

use strict; 
use warnings; 
use Data::Dumper; 

sub test1 { 
    my ($first, @rest, $last) = @_; 

    print Dumper \@rest; 

    print "First = $first, last = $last, rest = @rest\n"; 
} 

sub test2 { 
    my ($first, $second) = @_; 
    print "@$first ; @$second"; 
} 

test1 (1, 2, 3, 4); 
test2 ([1,2], [ 3,4]); 

my @list1 = (1,2,3,4); 
my @list2 = (5,6,7,8); 

test1 (@list1, @list2); 
test2 (\@list1, \@list2); 

如果你想保持數組或散列完整,你需要通過引用或作爲最後一個參數傳遞它們。

你也可能會得到一個警告,如果你打開strictwarnings在這裏 - 這是它強烈推薦的原因之一 - 因爲$b%b是不一樣的。您還會收到關於奇數分配的警告:

Odd number of elements in hash assignment at line 5. 
Use of uninitialized value $b in print 
1

將參數傳遞給Perl子例程時,它們被平化爲一個由@_表示的單個列表。從概念上講,這意味着如果你沒有傳遞對數組或哈希的引用,你將會「丟失」一些數據。 「丟失」並不完全正確,因爲所有的數據都在那裏;它只是不在你期望的變量中。這方面的一個例子是:

sub f { 
    my (@a, @b) = @_; 

    say 'a: ' . join(', ', @a); 
    say 'b: ' . join(', ', @b); 
} 
f(qw(1 2 3), qw(a b c)); 

您將得到以下輸出:

a: 1, 2, 3, a, b, c 
b: 

發生這種情況,因爲第一陣列@a消耗的所有值從@_和那裏沒有更多的時間可以存儲在@b。 beforeEnd子例程中的散列同樣如此。 $c$d的值存儲在%b的內部。作爲一個例子,因爲我看不到變量的值,如果你通過

beforeEnd(1, (a => 1, b => 2), 'c', 3); 

你的子裏面,你得到的東西是這樣的:

$a = 1 
%b = (a => 1, b => 2, c => 3) 
$c = undef 
$d = undef 

你可以通過引用來解決這個你hash%b:

beforeEnd($a, \%b, $c, $d); 
1

子例程接受標量列表作爲參數。如果傳遞數組或散列,則會傳遞數組或散列的內容。這意味着,

f($a, %b, $c, $d) 

相同

f($a, $b_key_1, $b_val_1, $b_key_2, $b_val_2, $b_key_3, $b_val_3, $c, $d); 

多少在@_標量的應分配給%b? Perl的保持它的簡單和分配所有剩餘的標量,從而

my ($a, %b, $c, $d) = @_; 

my $a = $_[0];  # The first argument 
my %b = @_[1..$#_]; # All but the first argument 
my $c; 
my $d; 

,如果你傳遞給散列的引用這是最好真的沒有什麼不同。這避免了這個問題,而且效率更高。

use Data::Dumper qw(Dumper); 

sub beforeEnd { 
    my ($a, $b, $c, $d) = @_; 
    local $Data::Dumper::Terse = 1; 
    print "a is $a, b is ".Dumper($b).", c is $c, d is $d \n"; 
} 

beforeEnd($a, \%b, $c, $d); 

題外話你的代碼註釋:

  • 你不得不表示沒有參數的原型,預計(),但是你指望四強。擺脫那個原型。

  • 您應該避免使用$a$b作爲變量,因爲它可能與sort相關。

0

參數只能在子程序中作爲標量變量列表傳遞。

無論何時將參數傳遞給子例程,我們都需要傳遞散列引用(或數組,對象)。 ... ... ... print「傳遞參數$ a,$ b,$ c,$ d \ n」; ($ a,\%b,$ c,$ d);

sub beforeEnd() { 
    my ($a, $b, $c, $d) = @_; 
    print "a is $a, b is %$b, c is $c, d is $d \n"; 
} 
相關問題