如何将变量作为引用传递给函数,并在调用者中更改它们而无需返回

问题描述 投票:1回答:1

我需要将变量,列表和哈希传递给子例程,并从中获取更改而不返回。

此代码不起作用。

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

谢谢。

arrays list perl reference subroutine
1个回答
6
投票

原则上,几乎所有语言都希望传递引用调用者,指针或引用中数据结构的对象。在Perl中,这将作为参考-而您正在这样做。

但是随后在子目录中创建本地副本; [$one@list%hash 在子目录中lexical variablessub's scope的本地对象,对调用范围中的对象进行屏蔽/遮蔽。对这些所做的更改不会超出sub的范围。

相反,直接使用您传递的引用来写入调用者的数据。

sub foo { 

    my ($rscalar, $rary, $rhash) = @_;

    $$rscalar = 2;

    @$rary = (4,5,6);

    $rhash->{'key'} = 'valueModified'; 
}

foo(\$one, \@list, \%hash);

现在调用代码中的$one@list%hash已更改。有关使用参考的详细信息,请参见教程perlreftut和参考perlref

[请注意,foo(\@allLocalArgs);通过参数传递数组的引用,因此子级接收一个元素-该数组的引用。您可以执行此操作,但对于问题而言,它不是必需的,因此我将其删除并直接传递了参数列表。

[另外要注意的是,参数在@_中是别名的-因此,如果在子级中直接使用@_,则可以在调用方中更改数据。因此,如果要将标量变量作为foo($one)传递,则子集中的$_[0] = 2会更改调用方中的$one。我认为[[原则上最好避免]。如果要更改呼叫者的数据,则应使其尽可能明确;通过参考。


术语注释

Perl中的

A

list

”是一种难以捉摸的临时结构,用于在程序中四处移动数据。想一想堆栈中的一堆标量(值),它们将被使用并消失。也许将参数传递给函数(foo($v1, $v2)),或形成字符串(join '', $v1, $v2),或创建匿名数组引用([$v1, $v2]),等等。An

array

是多值variable。就像哈希(关联数组)一样,它是一个多值变量,与scalar相反,它是一个单值变量。
关于这一点已经写了很多;这里有一些容易出现的链接:Effective Perler article(带有更多文章的链接),以及Stackoverflow页面Perl array vs list

简而言之,您正在询问“标量,数组,哈希”。

© www.soinside.com 2019 - 2024. All rights reserved.