Is there a difference between Perl's shift versus assignment from @_ for subroutine parameters?

后端 未结 9 1475
刺人心
刺人心 2020-12-14 20:16

Let us ignore for a moment Damian Conway\'s best practice of no more than three positional parameters for any given subroutine.

Is there any difference between the t

相关标签:
9条回答
  • 2020-12-14 20:43

    At least on my systems, it seems to depend upon the version of Perl and architecture:

    #!/usr/bin/perl -w
    use strict;
    use warnings;
    use autodie;
    
    use Benchmark qw( cmpthese );
    
    print "Using Perl $] under $^O\n\n";
    
    cmpthese(
        -1,
        {
            shifted   => 'call( \&shifted )',
            list_copy => 'call( \&list_copy )',
        }
    );
    
    sub call {
        $_[0]->(1..6);  # Call our sub with six dummy args.
    }
    
    sub shifted {
        my $foo   = shift;
        my $bar   = shift;
        my $baz   = shift;
        my $qux   = shift;
        my $quux  = shift;
        my $corge = shift;
    
        return;
    }
    
    sub list_copy {
        my ($foo, $bar, $baz, $qux, $quux, $corge) = @_;
        return;
    }
    

    Results:

    Using Perl 5.008008 under cygwin
    
                  Rate   shifted list_copy
    shifted   492062/s        --      -10%
    list_copy 547589/s       11%        --
    
    
    Using Perl 5.010000 under MSWin32
    
                  Rate list_copy   shifted
    list_copy 416767/s        --       -5%
    shifted   436906/s        5%        --
    
    
    Using Perl 5.008008 under MSWin32
    
                  Rate   shifted list_copy
    shifted   456435/s        --      -19%
    list_copy 563106/s       23%        --
    
    Using Perl 5.008008 under linux
    
                  Rate   shifted list_copy
    shifted   330830/s        --      -17%
    list_copy 398222/s       20%        --
    

    So it looks like list_copy is usually 20% faster than shifting, except under Perl 5.10, where shifting is actually slightly faster!

    Note that these were quickly derived results. Actual speed differences will be bigger than what's listed here, since Benchmark also counts the time taken to call and return the subroutines, which will have a moderating effect on the results. I haven't done any investigation to see if Perl is doing any special sort of optimisation. Your mileage may vary.

    Paul

    0 讨论(0)
  • 2020-12-14 20:43

    Usually I use the first version. This is because I usually need to have error checking together with the shifts, which is easier to write. Say,

    sub do_something_fantastical {
        my $foo   = shift || die("must have foo");
        my $bar   = shift || 0;  # $bar is optional
        # ...
    }
    
    0 讨论(0)
  • 2020-12-14 20:45

    There's a functional difference. The shift modifies @_, and the assignment from @_ does not. If you don't need to use @_ afterward, that difference probably doesn't matter to you. I try to always use the list assignment, but I sometimes use shift.

    However, if I start off with shift, like so:

     my( $param ) = shift;
    

    I often create this bug:

     my( $param, $other_param ) = shift;
    

    That's because I don't use shift that often, so I forget to get over to the right hand side of the assignment to change that to @_. That's the point of the best practice in not using shift. I could make separate lines for each shift as you did in your example, but that's just tedious.

    0 讨论(0)
提交回复
热议问题