Perl переменные области видимо не взаимодействуют - PullRequest
2 голосов
/ 25 февраля 2020

Все мои переменные объявлены в формате 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 is $date = $date->add(days => (3 - $date->day_of_week) % 7);

Проблема в том, что изменения, которые я делаю $date в моем вспомогательном методе, сохраняются при каждом вызове метода из mainMethod Примечание: я ничего не возвращаю

Например, если вместо $dt было 5, а helper было $date + 2, я бы получил

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

вместо ожидаемых 5 для каждого ответа.

Есть ли какой-то шаг, который мне не хватает для сброса этих переменных в конце метода?

Ответы [ 2 ]

4 голосов
/ 25 февраля 2020

Это не имеет ничего общего с областью видимости. Ваш объект 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() функция. Передача скалярного значения, подобного этому, создает копию, но поскольку переменная содержит только ссылку на другое место в памяти, она копирует этот указатель . Он по-прежнему будет указывать на то же место в памяти, поэтому любые внесенные в него изменения будут отражены в вашем исходном объекте DateTime.

4 голосов
/ 25 февраля 2020

DateTime создает ссылку .

Поэтому, когда вы звоните helper($dt), вы передаете копию ссылки на helper. Он не создает совершенно новый объект DateTime.

Любые изменения, которые вы вносите в передаваемое вами значение, вносятся в один объект DateTime, который вы уже создали.

Если вы хотите создать три различные объекты DateTime, тогда вам нужно вызвать DateTime->new три раза.

...