Passing arrays in Perl
All right, I'll try to e开发者_运维知识库xplain what I've done so far. I'm using a Parellel::ForkManager to grab data from an array of URLs, which is then stored in variables (value1, value2, value3).
I then collect the data from all of those processes, and display the data with $pm->run_on_finish
.
#...
my $pm = new Parallel::ForkManager(10);
$pm->run_on_finish (
sub {
my @info = @{$data_structure_reference};
print $info[0];
print $info[1];
print $info[2];
}
);
for my $var (@urls) {
$pm->start and next;
#...
@returned = &something($var);
#...
$pm->finish(0, \@returned);
}
sub something {
#... getting data from each URL and storing it in variables
my @array = (
$value1,
$value2,
$value3
);
return @array;
}
Now, what I want to do, is to pass an array, @value4
, as well, and then only display that data if there is something in the array. So, I want it to look like this:
sub something {
#... getting data from each URL and storing it in variables
my @array = (
$value1,
$value2,
$value3,
@value4
);
return @array;
}
And then I want it to print that array, only if there is something in it.
Unfortunately, I'm not entirely sure how to go about doing that.
I assume that what you are asking is how to return an array along with the three scalars returned from the something()
sub, and print it?
I also assume that those three scalars are what's referred to as being in @info
.
The simplest way seems to me to be to simply tack them to the end of the array you return, use the three first values, and if there's anything left, print that too.
$pm->run_on_finish (
sub {
my @info = @{$data_structure_reference};
print splice @info, 0, 3;
print @info if (@info);
}
);
sub something {
return (
$value1,
$value2,
$value3,
@value4
);
}
As you'll notice, you do not need to fill a dummy array for the return value, simply return values inside the parens. You do not need to dereference the array, since you can use the @info
array straight up if you splice off the first three values.
I like it simple. If it works.
I've previously provided a simple solution to this problem. It can use threads (use threads;
) or processes (use forks;
).
use threads; # or: use forks;
use Thread::Queue qw( );
use constant NUM_WORKERS => 10;
my $request_q = Thread::Queue->new();
my $response_q = Thread::Queue->new();
# Create the workers.
for (1..NUM_WORKERS) {
(async {
while (defined(my $request = $request_q->dequeue())) {
$response_q->enqueue(process_request($request));
}
})->detach();
}
# Submit work to workers.
$request_q->enqueue(@requests);
# Signal the workers they are done.
$request_q->enqueue(undef) for 1..NUM_WORKERS;
# Collect the results.
my $working = NUM_WORKERS;
while ($working) {
my $result = $response_q->dequeue();
if (!defined($result)) {
--$working;
next;
}
process_response($result);
}
The work to be done in the children is done by process_request
.
sub process_request {
# ...
return [
$value1,
$value2,
$value3,
\@value4,
];
}
The results are passed to process_response
in the parent.
sub process_response {
my ($value1, $value2, $value3, $value4) = @{ $_[0] };
...
}
I am not totally sure what you are asking, but in order to pass multiple arrays to a function in Perl one must pass by reference.
my @array1 = (1, 2, 3);
my @array2 = ('a', 'b', 'c');
&fn(\@array1, \@array2);
In order to print an array only in the case when it has value, one must simply check that it has value and print it:
print "@array" if @array;
Though, the nice function of "@array"
is that if @array
has no value then "@array"
evaluates to ""
. This allows you to reduce the previous statement to a simple:
print "@array"
精彩评论