Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Perl variable scopes seemingly not cooperating

Tags:

scope

perl

All my variables are declared following my $var format.

In my program I call mainMethod()

Then in mainMethod I define a DateTime variable and then pass it to a separate helper method 3 times.:

 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,);

In helper I start with:

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

This method does a lot of different things but the only changes I make to $date is $date = $date->add(days => (3 - $date->day_of_week) % 7);

The problem is, it seems like the changes I make $date in my helper method, persist through each time I call the method from mainMethod Note: I'm not returning anything

For example, if $dt was instead 5 and helper was $date + 2 I would get

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

Instead of the expected 5 for every response.

Is there some step that I'm missing to reset those variables at the end of the method?

like image 366
AndyReifman Avatar asked Jun 14 '26 07:06

AndyReifman


2 Answers

DateTime creates a reference.

So when you call helper($dt) you pass a copy of the reference to helper. It doesn't create a whole new DateTime object.

Any changes you make to the value you pass are made to the single DateTime object you have already created.

If you want to create three different DateTime objects, then you need to call DateTime->new three times.

like image 139
Quentin Avatar answered Jun 16 '26 21:06

Quentin


This has nothing to do with scoping. Your DateTime object is a reference. That's how objects work in Perl.

To explain what's going on, I will use a simpler data structure. An array reference works just the same way.

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;
}

The output of this program will be

1
1 1
1 1 1

Just like with your DateTime object, we're passing a reference to the helper() function. Passing a scalar value like this creates a copy, but because the variable only contains a reference to somewhere else in memory, it copies that pointer. It will still point at the same place in memory, so any changes you make to that will be reflected in your original DateTime object.

like image 27
simbabque Avatar answered Jun 16 '26 21:06

simbabque