MrDuk
MrDuk

Reputation: 18322

How to deref @$_?

I'm doing this:

sub worker {
    my ($job, @action) = @$_; #<-- error thrown here
    Build($job, @action[0]);
}


for (1..NUM_WORKERS) {
  async {
     while (defined(my $job = $q->dequeue())) {
        worker($job);
     }
  };
}

$q->enqueue([$_, 'clean']) for @compsCopy;

# When you're done adding to the queue.
$q->end();
$_->join() for threads->list();

When this executes, I get:

Thread 8 terminated abnormally: Can't use string ("8") as an ARRAY ref while "strict refs" in use (@ the line referenced above)

What am I doing wrong here?

edit: To give more insight into what I'm trying to accomplish, I want to be able to do something like:

$q->enqueue([$_, 'clean']) for @compsCopy; #clean
$q->enqueue([$_, 'l1']) for @compsCopy; #build
$q->enqueue([$_, '']) for @compsCopy; #link

Where a user could specify when they're running the script, which $actions they want to perform on the components (directories).

Upvotes: 2

Views: 99

Answers (1)

Miller
Miller

Reputation: 35208

If the first parameter to worker is an array reference, then you do the following:

sub worker {
    my ($job, @action) = @{$_[0]}; 

$_ and @_ may look similar but they are different variables. Use the array @_ for accessing the parameters passed to that subroutine. $_[0] will hold the first element of that array.

Note: I'd advise that you come up with a different name for the first captured parameter to the worker sub. Reusing $job is confusing. Inside the sub it looks like my ($val, @action) = ... might be more semantically accurate.


Now, if we undo all the changes the OP made, we get back something that uses a saner parameter order and a doesn't use the name $job for two different things.

sub worker {
    my ($job) = @_;
    my ($job_type, @job_params) = @$job;

    if ($job_type eq 'clean') {
        clean(@job_params);
    }
    # elsif ($job_type eq '...') {
    #    ...
    # }
    # ...
}


for (1..NUM_WORKERS) {
  async {
     while (defined(my $job = $q->dequeue())) {
        worker($job);
     }
  };
}

$q->enqueue([ clean => $_ ]) for @compsCopy;

# When you're done adding to the queue.
$q->end();
$_->join() for threads->list();

Upvotes: 5

Related Questions