dzookatz dzookatz - 7 months ago 15
Perl Question

Manipulate Perl object by reference in subroutine

I have a Perl program and packages

Worker
and
Log
.

The Worker does almost all calculations, and I want to pass an object by reference to the Worker subroutine, as well as some other parameters (scalar and an array). I have seen examples like this and this.

They handle this by putting
@_
in subs, then manipulating the object. I also found a way to manipulate them by using the index, like
@{$_[i]}
. Problem is, when I try the code like so, I get an error:
Can't call method "write" on unblessed reference at ...


Code snippets below.

Main:

use strict;
use warnings;
use Log;
use Worker;

my $log = Log->new();
my $worker = Worker->new();
my $scalar = "SomeURLhere";
my @array = ('red','blue','white');

# I do some stuff with $log object
#...
# Now I want to pass data to the Worker
$worker->subFromWorker($scalar, \$log, \@array);


Worker:



use strict;
use warnings;
package Worker;

sub new {
my $class = shift;
my $self = {};
bless $self, $class;
return $self;
}

sub subFromWorker{
my ($self) = shift;
my $scalar = $_[0];
#my ($log) = $_[1];
my @array = @{$_[2]};

foreach my $item (@array){
print $item;
}

$_[1]->write("The items from url $scalar are printed.");

#Same thing happens if I use $log here
}


In C#, this is handled in a different way - you can send a parameter to a method by value or by reference, and then do what you want in a specialized method (method is pre-written to handle parameters by reference or value). I thought that in Perl sending using
\parameter
will send the reference.

Answer

Objects are references. References are scalar values.

If you want to pass arrays or hashes into a subroutine then you usually want to pass references to them - because Perl parameter passing works far better with scalar values.

But $log is already a reference to your object. Therefore you don't need to take a reference to it. You end up passing a reference to a reference. So when you copy that parameter into $log inside your subroutine you have an extra, unnecessary, level of references.

The fix is to just pass the $log scalar into the subroutine.

$worker->subFromWorker($scalar, $log, \@array); # $log, not \$log

Everything else will then work fine.

Comments