Perl - 传递对子例程的引用
我在理解 Perl 中的引用时遇到困难。这是一个简短的 perl 脚本来解释我的问题 [我使用 perl-5.8.3 运行此代码]:
#!/usr/bin/perl -w
use strict;
use Data::Dumper;
my %a = ("a" => 1, "b" => 2);
my %b = ();
print Dumper(\%a, \%b);
foo(\%a, \%b);
print "+==After fn call==+\n";
print Dumper(\%a, \%b);
print "+-----------------------+\n";
bar(\%a, \%b);
print "+==After fn call==+\n";
print Dumper(\%a, \%b);
sub foo {
my($h1, $h2) = @_;
$h2 = $h1;
print Dumper($h2);
}
sub bar {
my($h1, $h2) = @_;
%{$h2} = %{$h1};
}
我猜在两个子例程中, $h1 和 $h2 都是本地变量。尽管如此, bar() 实际上改变了原始 %b 的值,而 foo() 则没有。这是为什么?
I am facing difficulty understanding references in perl. Here is a short perl script to explain my problem [I ran this code using perl-5.8.3]:
#!/usr/bin/perl -w
use strict;
use Data::Dumper;
my %a = ("a" => 1, "b" => 2);
my %b = ();
print Dumper(\%a, \%b);
foo(\%a, \%b);
print "+==After fn call==+\n";
print Dumper(\%a, \%b);
print "+-----------------------+\n";
bar(\%a, \%b);
print "+==After fn call==+\n";
print Dumper(\%a, \%b);
sub foo {
my($h1, $h2) = @_;
$h2 = $h1;
print Dumper($h2);
}
sub bar {
my($h1, $h2) = @_;
%{$h2} = %{$h1};
}
I guess in both subroutines, $h1 and $h2 are local vars. Still, bar() actually changes value of original %b, while foo() does not. Why is that?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
如果值包含字符串或任何其他简单值,这与您将得到的行为完全相同。
所以基本上,在第一个示例中,您只是处理值,并且应用正常的值语义。在第二种情况下,您取消引用这些值,这会将它们恢复为高级类型(在本例中为 HASH)。
this is the same exact behavior you would get if the values contained strings or any other simple value.
So basically, in the first example, you are just dealing with values, and normal value semantics apply. In the second case, you are dereferencing the values, which turns them back into their advanced types (in this case a HASH).
$h2
是一个保存引用的词法变量。更改$h2
只是替换其中的引用。%{$h2}
是$h2
(又名%b
)引用的哈希,因此更改%{$h2}< /code>(又名
%b
)更改$h2
(又名%b
)引用的哈希值。您似乎期望更改一个变量(
$h2
)会更改另一个变量(%b
),但我不知道您为什么有这样的期望。它们甚至不是相同的变量类型!当标量没有元素时(至少与哈希不同),如何尝试通过更改标量来更改哈希的元素。$h2
is a lexical var that holds a reference. Changing$h2
just replaces the reference therein.%{$h2}
is the hash referenced by$h2
(aka%b
), so changing%{$h2}
(aka%b
) changes the hash referenced by$h2
(aka%b
).You seem to be expecting that changing one variable (
$h2
) will change another (%b
), but I have no idea why you have any such expectation. They're not even the same variable type! How can one even try to change the elements of a hash by changing a scalar when a scalar doesn't have elements (at least not in the same sense as a hash does).Eric Strom 是正确的,但让我们看看是否可以用另一种方式解释这一点:
}
让我们让事情变得更简单:
$h1
指向内存位置 #1,$h2
指向内存位置#2。您的语句$h2 = $h1
现在也使$h2
指向内存位置 #1。内存位置 #1 的内容是否已更改?否。内存位置 #2 的内容是否已更改?不会。
一旦离开子例程,
$h1
和$h2
就不再存在。当您说
%{$h1}
时,您现在正在谈论内存位置 #1 的内容。您在作业中所做的是将内存位置 #1 的内容复制到内存位置 #2。请注意,$h1
仍然指向内存位置#1,而$h2
仍然指向内存位置#2。因此,$h1
和$h2
的值不会改变,但它们指向的内容会改变。现在,让我们看看
%a
和%b
。%a
的内容位于内存位置#1,%b
的内容位于内存位置#2。在sub foo
中,我们没有改变内存位置#2中的信息,因此%b
的值没有改变。在
sub bar
中,我们弄乱了内存位置#2的内容,因此%b
的值(将其内容存储在内存位置#2中)发生了变化。顺便说一下,请注意,在子例程调用之后更改
%a
根本不会更改%b
。它们可能共享相同的内容,但它们不是相同的变量。Eric Strom is correct, but let's see if we can explain this another way:
}
Let's make things easier:
$h1
points to memory location #1 and$h2
points to memory location #2. Your statement$h2 = $h1
now makes$h2
point to memory location #1 too.Has the contents of memory location #1 changed? No. Has the contents of memory location #2 changed? No.
Once you leave the subroutine,
$h1
and$h2
no longer exist.When you say
%{$h1}
, you're now talking about the contents of memory location #1. What you're doing in your assignment is copying the contents of memory location #1 to memory location #2. Notice that$h1
still points to memory location #1 and$h2
still points to memory location #2. Thus, the values of$h1
and$h2
don't change, but what they point to does change.Now, let's look at
%a
and%b
. The contents of%a
were in memory location #1 and the contents of%b
were in memory location #2. Insub foo
, we didn't change the information in memory location #2, so the value of%b
didn't change.In
sub bar
, we messed with the contents of memory location #2, so the value of%b
(which stores its contents in memory location #2) has changed.By the way, note that changing
%a
after the subroutine call doesn't change%b
at all. They might share the same contents, but they aren't the same variable.这与传递或子例程无关。这只会让问题变得混乱。如果您考虑相同的代码而不调用子例程,您会更好地理解它:
This has nothing to do with passing or subroutines. That just confuses the issue. You'll understand it better if you consider the same code without calling subroutines: