Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In Perl, why am I getting a warning when I use @_[0], @_[1], etc to access arguments to my subroutine?

Tags:

warnings

perl

The below one the code.

sub max 
    {
        if (@_[0] > @_[1]) 
        {
            @_[0];
        }
        else
        {
            @_[1];
        }
    }
    print "biggest is ".&max(37,25);

When I ran it, I got the following warnings,

Scalar values @_[0] better written as $_[0] at file.pl line 3.
Scalar values @_[1] better written as $_[1] at file.pl line 3.
Scalar values @_[0] better written as $_[0] at file.pl line 5.
Scalar values @_[0] better written as $_[0] at file.pl line 9.
biggest is 37.

Although I got a correct output, but I wonder what could be the reason behind this warning, Since I think that using @_ in a subroutine would be apropriate than $_.

like image 465
Praveen kumar Avatar asked Apr 15 '13 10:04

Praveen kumar


3 Answers

The problem is that you are referring to your single array element by using an array slice instead of a scalar. Just like the error says. An array slice is a list of elements from an array, for example:

my @a = (0 .. 9);
print @a[0,3,4];    # prints 034

Conversely, when you refer to a single array element you use the scalar prefix $:

print $a[3];        # prints 3

So when you do

@_[0];

Perl is telling you that the proper way to refer to a scalar value is by not using an array slice, but rather to use the scalar notation:

$_[0];

That is all.

like image 136
TLP Avatar answered Nov 08 '22 23:11

TLP


Try to understand it with this example:

@array = (1,2,3); #array is the name of the array and @ means that it's an array
print $array[1];  
#this will print element at index 1 and you're doing it in scalar context

Similarly,

@_ = (1,2,3); #_ is the name of the array
print $_[1]; 
#this will print element at index 1 of array _ and again you're doing it in scalar context
like image 40
A human being Avatar answered Nov 09 '22 00:11

A human being


You are referring to an array, instead of a scalar. @_[0] means ($_[0]). But perl is kind of clever so it warns You that instead of an explicit single element list You should return a scalar. Here You should use $_[0].

I suggest to use prototype, as now You could call max (1, 2, 3) and the result will be 2, instead of 3. So define as

sub max ($$) { $_[0] > $_[1]) ? $_[0] : $_[1] }

Or better, You can use for undefined number (>=2) of elements. Maybe pointless to call it with 0 or 1 items.

sub max (@) { 
    return undef if $#_<0; 
    my $s = shift; 
    for(@_) { $s = $_ if $_ > $s } $s 
} 
like image 21
TrueY Avatar answered Nov 08 '22 22:11

TrueY