如何将变量作为引用传递给函数并在调用者中更改它们而不返回
How to pass variables to a function as reference and get them changed in caller without returning
我需要将变量、列表和散列传递给子例程,并在不返回的情况下从中取回更改。
此代码无法完成工作。
sub foo{
my $one = {$_[0]};
my @list = @{$_[1]};
my %hash = %{$_[2]};
print("\n inside foo: ${one}\n");
print("\n inside foo: $one @list $hash{'key'}\n");
$one = 2;
@list = (4,5,6);
my %hash2;
$hash2{'key'} = 'valueModified';
%hash = %hash2;
print("\n inside foo after Mod: $one\n");
print("\n inside foo after Mod: $one @list $hash{'key'}\n");
}
my $one = 1;
my @list = (1,2,3);
my %hash;
$hash{'key'} = 'value';
my @allLocalArgs = ($one,\@list,\%hash);
foo(\@allLocalArgs);
print("\nafter foo modification: $one @list $hash{'key'}\n");
输出:
inside foo: HASH(0x234a240)
inside foo: HASH(0x234a240)
inside foo after Mod: 2
inside foo after Mod: 2 4 5 6 valueModified
after foo modification: 1 1 2 3 value
谢谢。
原则上,实际上在任何语言中,您都希望传递引用调用方数据结构的对象、指针或引用。在 Perl 中,这将是一个引用——而您正在这样做。
但随后在 sub 中创建本地副本; sub 中的 $one
、@list
和 %hash
是 lexical variables
局部于 sub's scope,masking/shadowing 在调用范围内。对那些的更改不会超出子范围。
而是直接使用您传递的引用来写入调用者的数据。
sub foo {
my ($rscalar, $rary, $rhash) = @_;
$$rscalar = 2;
@$rary = (4,5,6);
$rhash->{'key'} = 'valueModified';
}
foo($one, \@list, \%hash);
现在更改了调用代码中的$one
、@list
和%hash
。有关使用引用的详细信息,请参阅教程 perlreftut and reference perlref.
请注意,foo(\@allLocalArgs);
通过参数传递数组的引用,因此 sub 接收一个元素——该数组的引用。您可以这样做,但就问题而言,不需要它,因此我将其删除并直接传递了参数列表。
另一件需要注意的事情是参数在 @_
中使用了别名——所以如果在子程序中您直接使用 @_
那么您可以更改调用者中的数据。因此,如果您要将标量变量作为 foo($one)
传递,则子程序中的 $_[0] = 2
会更改调用者中的 $one
。 我认为原则上最好避免这种情况;如果要更改调用者的数据,则应尽可能明确;通过引用。
术语说明
Perl 中的 list 是一种难以捉摸的临时结构,用于在程序中移动数据;想想堆栈中某处的一堆标量(值),即将被使用并消失。也许将参数传递给一个函数(foo($v1, $v2)
),或者形成一个字符串(join '', $v1, $v2
),或者创建一个匿名数组引用([$v1, $v2]
),等等
另一方面,数组是multi-valued变量。很像散列(关联数组)是一个 multi-valued 变量,而不是 标量 ,是一个 single-valued 变量。
关于这个已经写了很多;这里有一些很容易出现的链接:Effective Perler article (with links to a few more articles), and a Whosebug page Perl array vs list.
简而言之,你问的是"scalar, array, hash."
我需要将变量、列表和散列传递给子例程,并在不返回的情况下从中取回更改。
此代码无法完成工作。
sub foo{
my $one = {$_[0]};
my @list = @{$_[1]};
my %hash = %{$_[2]};
print("\n inside foo: ${one}\n");
print("\n inside foo: $one @list $hash{'key'}\n");
$one = 2;
@list = (4,5,6);
my %hash2;
$hash2{'key'} = 'valueModified';
%hash = %hash2;
print("\n inside foo after Mod: $one\n");
print("\n inside foo after Mod: $one @list $hash{'key'}\n");
}
my $one = 1;
my @list = (1,2,3);
my %hash;
$hash{'key'} = 'value';
my @allLocalArgs = ($one,\@list,\%hash);
foo(\@allLocalArgs);
print("\nafter foo modification: $one @list $hash{'key'}\n");
输出:
inside foo: HASH(0x234a240)
inside foo: HASH(0x234a240)
inside foo after Mod: 2
inside foo after Mod: 2 4 5 6 valueModified
after foo modification: 1 1 2 3 value
谢谢。
原则上,实际上在任何语言中,您都希望传递引用调用方数据结构的对象、指针或引用。在 Perl 中,这将是一个引用——而您正在这样做。
但随后在 sub 中创建本地副本; sub 中的 $one
、@list
和 %hash
是 lexical variables
局部于 sub's scope,masking/shadowing 在调用范围内。对那些的更改不会超出子范围。
而是直接使用您传递的引用来写入调用者的数据。
sub foo {
my ($rscalar, $rary, $rhash) = @_;
$$rscalar = 2;
@$rary = (4,5,6);
$rhash->{'key'} = 'valueModified';
}
foo($one, \@list, \%hash);
现在更改了调用代码中的$one
、@list
和%hash
。有关使用引用的详细信息,请参阅教程 perlreftut and reference perlref.
请注意,foo(\@allLocalArgs);
通过参数传递数组的引用,因此 sub 接收一个元素——该数组的引用。您可以这样做,但就问题而言,不需要它,因此我将其删除并直接传递了参数列表。
另一件需要注意的事情是参数在 @_
中使用了别名——所以如果在子程序中您直接使用 @_
那么您可以更改调用者中的数据。因此,如果您要将标量变量作为 foo($one)
传递,则子程序中的 $_[0] = 2
会更改调用者中的 $one
。 我认为原则上最好避免这种情况;如果要更改调用者的数据,则应尽可能明确;通过引用。
术语说明
Perl 中的 list 是一种难以捉摸的临时结构,用于在程序中移动数据;想想堆栈中某处的一堆标量(值),即将被使用并消失。也许将参数传递给一个函数(foo($v1, $v2)
),或者形成一个字符串(join '', $v1, $v2
),或者创建一个匿名数组引用([$v1, $v2]
),等等
另一方面,数组是multi-valued变量。很像散列(关联数组)是一个 multi-valued 变量,而不是 标量 ,是一个 single-valued 变量。
关于这个已经写了很多;这里有一些很容易出现的链接:Effective Perler article (with links to a few more articles), and a Whosebug page Perl array vs list.
简而言之,你问的是"scalar, array, hash."