Perl变量范围似乎不合作

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

我的所有变量都以my $var格式声明。

在我的程序中,我叫mainMethod()

然后在mainMethod中定义一个DateTime变量,然后将其传递给单独的辅助方法3次。:

 my ($day,$month,$year)=(localtime)[3,4,5];
 my $dt = DateTime->new(
    year      => $year,
    month     => 2 + $month,
    day       => 1,
    hour      => 8,
    minute    => 30,
    time_zone => 'America/New_York'
);
helper($dt, $year, $month, $day,);
helper($dt,$year, $month, $day,);
helper($dt,$year, $month, $day,);

helper中,我从以下位置开始:

my $date = $_[0];
my ($year, $month, $day) = ($_[1],$_[2],$_[3]);

[此方法做了很多不同的事情,但我对$date所做的唯一更改是$date = $date->add(days => (3 - $date->day_of_week) % 7);

问题是,似乎我在辅助方法中进行的$date更改在每次从mainMethod调用该方法时都会持续存在,注意:我什么都不返回

例如,如果$dt改为5helper等于$date + 2,我会得到

helper($dt) #output: 7
helper($dt) #output: 9
helper($dt) #output: 11

而不是每个响应预期的5。

在方法结束时是否缺少一些步骤来重置这些变量?

perl scope
2个回答
4
投票

[DateTime创建一个reference

因此,当您调用helper($dt)时,会将引用的副本传递给helper。它不会创建一个全新的DateTime对象。

对传递的值所做的任何更改都会对已经创建的单个DateTime对象进行。

如果要创建三个不同的DateTime对象,则需要调用DateTime->new 3次。


4
投票

这与范围界定无关。您的DateTime对象是一个引用。这就是对象在Perl中的工作方式。

为了解释正在发生的事情,我将使用一个更简单的数据结构。数组引用的工作方式相同。

my $foo = [];

helper($foo);
print "@$foo\n";

helper($foo);
print "@$foo\n";

helper($foo);
print "@$foo\n";

sub helper {
    my $bar = $_[0];
    push @$bar, 1;
}

此程序的输出为

1
1 1
1 1 1

就像您的DateTime对象一样,我们正在传递对helper()函数的引用。像这样传递标量值将创建一个副本,但是由于变量仅包含对内存中其他位置的引用,因此它将复制该[[pointer。它仍将指向内存中的同一位置,因此您对此所做的任何更改都将反映在原始DateTime对象中。

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