Perl 将参数传递给子例程不起作用
Perl Passing arguments to subroutine not working
我正在尝试将参数传递给 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";
}
打印语句的输出让我知道出了什么问题。奇怪的部分?前 2 个参数正确传递。
> Passing arguments 1, (1,2,3), 2, 3
> a is 1, b is (1,2,3), c is , d is
如有任何帮助,我们将不胜感激。
当参数传递给 Perl 子例程时,它们被展平到一个由 @_
表示的列表中。从概念上讲,这意味着如果您不传递对数组或散列的引用,您将 "lose" 一些数据。 "Lose" 不完全正确,因为所有数据仍然存在;它只是不在您期望的变量中。例如:
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
您可以通过传递对哈希 %b 的引用来解决此问题:
beforeEnd($a, \%b, $c, $d);
因为当您将参数传入或传出子例程时,任何散列和数组都会被粉碎。
您正在向 %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 );
如果您想保持数组或散列的完整性,您需要通过引用或将它们作为最后一个参数传递。
如果您在此处打开 strict
和 warnings
,您也可能会收到警告 - 这是强烈推荐的原因之一 - 因为 $b
和 %b
不一样。您还会收到关于作业数量为奇数的警告:
Odd number of elements in hash assignment at line 5.
Use of uninitialized value $b in print
子例程接受标量列表作为参数。如果传递数组或散列,则会传递数组或散列的内容。也就是说
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
.
参数只能作为标量变量列表在子例程中传递。
每当将参数传递给子例程时,我们都需要传递散列(或数组、对象)的引用。
...
...
...
打印"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";
}
我正在尝试将参数传递给 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";
}
打印语句的输出让我知道出了什么问题。奇怪的部分?前 2 个参数正确传递。
> Passing arguments 1, (1,2,3), 2, 3
> a is 1, b is (1,2,3), c is , d is
如有任何帮助,我们将不胜感激。
当参数传递给 Perl 子例程时,它们被展平到一个由 @_
表示的列表中。从概念上讲,这意味着如果您不传递对数组或散列的引用,您将 "lose" 一些数据。 "Lose" 不完全正确,因为所有数据仍然存在;它只是不在您期望的变量中。例如:
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
您可以通过传递对哈希 %b 的引用来解决此问题:
beforeEnd($a, \%b, $c, $d);
因为当您将参数传入或传出子例程时,任何散列和数组都会被粉碎。
您正在向 %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 );
如果您想保持数组或散列的完整性,您需要通过引用或将它们作为最后一个参数传递。
如果您在此处打开 strict
和 warnings
,您也可能会收到警告 - 这是强烈推荐的原因之一 - 因为 $b
和 %b
不一样。您还会收到关于作业数量为奇数的警告:
Odd number of elements in hash assignment at line 5.
Use of uninitialized value $b in print
子例程接受标量列表作为参数。如果传递数组或散列,则会传递数组或散列的内容。也就是说
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
.
参数只能作为标量变量列表在子例程中传递。
每当将参数传递给子例程时,我们都需要传递散列(或数组、对象)的引用。 ... ... ... 打印"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";
}