Where does a Perl function get values ​​that are not in real parameters?

I came across the following Perl routine get_billable_pages

while chasing a bug. It takes 12 arguments.

sub get_billable_pages {
    my ($dbc,
        $bill_pages,      $page_count,      $cover_page_count,
        $domain_det_page, $bill_cover_page, $virtual_page_billing,
        $job,             $bsj,             $xqn,
        $direction,       $attempt,
    ) = @_;

    my $billable_pages = 0;

    if ($virtual_page_billing) {
        my @row;
        ### Below is testing on the existence of the 11th and 12th parameters ###
        if ( length($direction) && length($attempt) ) {
            $dbc->xdb_execute("
                SELECT convert(int, value)
                FROM   job_attribute_detail_atmp_tbl
                WHERE  job             = $job
                AND    billing_sub_job = $bsj
                AND    xqn             = $xqn
                AND    direction       = '$direction'
                AND    attempt         = $attempt
                AND    attribute       = 1
            ");
        }
        else {
            $dbc->xdb_execute("
                SELECT convert(int, value)
                FROM job_attribute_detail_tbl
                WHERE job             = $job
                AND   billing_sub_job = $bsj
                AND   xqn             = $xqn
                AND   attribute       = 1
            ");
        }
        $cnt = 0;
        ...;

      

But sometimes it is called with only 10 arguments

$tmp_det = get_billable_pages(
    $dbc2,
    $row[6],          $row[8],          $row[7],
    $domain_det_page, $bill_cover_page, $virtual_page_billing,
    $job1,            $bsj1,            $row[3],
);

      

The function checks the 11th and 12th arguments.

  • What are the 11th and 12th arguments when only 10 arguments are passed to the function?

  • Is it a mistake to call a function with only 10 arguments, because the 11th and 12th arguments become random values?

  • I think this might be the source of the error, because the 12th argument had a funky meaning when the program failed.

  • I have not seen any other function definition that only takes 10 arguments.

+3


source to share


2 answers


The values ​​are copied from the parameter array @_

to the scalar variable list.

If the array is smaller than the list, then the redundant variables are set to undef

. If the array is longer than the list, then the extra array elements are ignored.

Note that the original array has @_

not been changed by the assignment. No values ​​are created or lost, so it remains the final source of the actual parameters passed when the subroutine is called.

ikegami suggested that I provide some Perl code to demonstrate assigning arrays to lists of scalars. Here is this Perl code based mainly on editing it

use strict;
use warnings;

use Data::Dumper;

my $x = 44;             # Make sure that we
my $y = 55;             # know if they change

my @params = (8);       # Make a dummy parameter array with only one value

($x, $y) = @params;     # Copy as if this is were a subroutine

print Dumper $x, $y;    # Let see our parameters
print Dumper \@params;  # And how the parameter array looks

      

Output



$VAR1 = 8;
$VAR2 = undef;

$VAR1 = [ 8 ];

      

Thus, both parameters $x

and $y

change, but if there are not enough values ​​in the array, it is used instead undef

. It is as if the original array was expanded with elements indefinitely undef

.

Now let's look at the logic of the Perl code. undef

evaluates to false for the purpose of conditional tests, but you are applying a statement length

like this

if ( length($direction) && length($attempt) ) { ... }

      

If you have use warnings

, as usual, Perl usually generates a warning Use of uninitialized value

. However, it length

is unusual in this case that if you are asking for the length of a value undef

(and you are using version 12 or later of Perl 5), it will simply return undef

rather than warn you.

As for "I have not seen any other function definition that only takes 10 arguments", Perl does not have function templates like C ++ and Java, then for the code it was accepted it depends on the code in the subroutine and behaves accordingly.

+4


source


No, this is not a mistake. The rest of the arguments are "undef" and you can check this situation.

sub foo {
    my ($x, $y) = @_;
    print " x is undef\n" unless defined $x;
    print " y is undef\n" unless defined $y;

}

foo(1);

      



prints

 y is undef

      

+2


source







All Articles