4

I have a method where I give two arguments: one array and one string. The problem is when I initialise two different variables, one for the array and one for the string, I get the first element of the array in the first variable and the second element in the second variable. My question is how can I get the whole array in a variable and the string in a different variable?

Analyze.pm

sub analyze {
    my $self = shift;
    my ($content, $stringToSearch) = @_; 
    # my ($stringToSearch) = @_;
    print "$stringToSearch";
    if (!defined($stringToSearch) or length($stringToSearch) == 0) { die 'stringToSearch is not defined yet! ' }
    foreach my $element ($content) {
        #print "$element";
        my $loc = index($element, $stringToSearch);
        # print "$loc\n";
        given ($stringToSearch) {
            when ($stringToSearch eq "Hi") {
                if ($loc != 0) {
                    print "Searched word is Hi \n"; 
                } else {
                    print "No word found like this one! "
                }
            }
            #when ($stringToSearch == 'ORIENTED_EDGE') {
            #   print 'Searched word is ORIENTED_EDGE';
            #} # Printed out because i dont need it now!
        }
        break; # For testing
    }
}

example.pm

my @fileContent = ('Hi', 'There', 'Its', 'Me')
my $analyzer = Analyze->new();
$analyzer->analyze(@fileContent, 'Hi');

When I change $content to @content it puts all the values of the array and the string in @content

I hope someone is able to help me. I'm a beginner in Perl. Thanks in advance

3
  • 2
    swap them?call analyze('Hi',@content) instead Commented Sep 5, 2019 at 6:57
  • 2
    easy to mess up with $ and @ , so i would suggest put all $ args in front of any @ arg , or use dict as arg completely Commented Sep 5, 2019 at 6:59
  • 2
    As an aside: break is not a Perl keyword. What you want here is probably last. Commented Sep 5, 2019 at 18:33

2 Answers 2

6

You can't pass arrays to subs (or methods), only a list of scalars. As such,

$analyzer->analyze(@lines, 'Hi');

is the same as as

$analyzer->analyze($lines[0], $lines[1], ..., 'Hi');

It means that the following won't work well:

my (@strings, $target) = @_;

Perl doesn't know how many items belonged to the original array, so it places them all in @strings, leaving $target undefined.


Solutions

You can do what you want as follows:

sub analyze {
    my $self = shift;
    my $target = pop;
    my @strings = @_
    for my $string (@strings) {
       ...
    }
}

$analyzer->analyze(@lines, 'Hi')

Or without the needless copy:

sub analyze {
    my $self = shift;
    my $target = pop;
    for my $string (@_) {
       ...
    }
}

$analyzer->analyze(@lines, 'Hi')

Passing the target first can be easier.

sub analyze {
    my ($self, $target, @strings) = @_;
    for my $string (@strings) {
       ...
    }
}

$analyzer->analyze('Hi', @lines)

Or without the needless copy:

sub analyze {
    my $self = shift;
    my $target = shift;
    for my $string (@_) {
       ...
    }
}

$analyzer->analyze('Hi', @lines)

You could also pass a reference to the array (in any order you like) since a reference is a scalar.

sub analyze {
    my ($self, $target, $strings) = @_;
    for my $string (@$strings) {
       ...
    }
}

$analyzer->analyze('Hi', \@lines)

I would go with the second to last. It follows the same general pattern as the well-known grep.

my @matches = grep { condition($_) } @strings;
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for the explanation! I'm a new to perl so I appreciate it.
0

I'd just like to add a slightly different method of passing an array to a subroutine.

# Begin main program
my @arr=(1,2,3);
my $i=0;
mysub(\@arr,$i); # Pass the reference to the array

exit; # Exit main program
##########
sub mysub
{my($aref,$i)=@_; # We are receiving an array ref. 

my @arr=@$aref; # Now we are back to a regular array.
print "$arr[0]\n$arr[1]\n$arr[2]\n";

return;
}

2 Comments

Passing a reference was already mentioned. All you added is my @arr=@$aref;. That's awful! Don't even do that!!! You're copying all the elements for nothing!
@ikegami It's not awful, it helps beginners understand how references work. This shouldn't be an elitist site for advanced people only.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.