Beefy Boxes and Bandwidth Generously Provided by pair Networks
Your skill will accomplish
what the force of many cannot
 
PerlMonks  

Argument Passing, preference or performance ?

by the_Don (Scribe)
on Nov 11, 2002 at 21:27 UTC ( [id://212101]=perlquestion: print w/replies, xml ) Need Help??

the_Don has asked for the wisdom of the Perl Monks concerning the following question:

I have seen two different methods of assigning my-type variables from passed in arguments. The two ways I am talking about is shown below:
sub routine1 { my ($var_one, $var_two, $var_three) = @_; ... } sub routine2{ my $var_one = shift; my $var_two = shift; my $var_three = shift; ... }

So, my question is "What are the benefits, drawbacks relating to performance of the two ways, if any?" I know that shift reduces the array by one, and then the leftovers are typically used in loops, etc... I have not been able to see anything that explains any other difference, so are the two methods relatively equal in execution time, and therefore the ultimate decision is preference of the coder?

the_Don
...making offers others can't rufuse.

Replies are listed 'Best First'.
Re: Argument Passing, preference or performance ?
by dws (Chancellor) on Nov 11, 2002 at 21:50 UTC
    ... so are the two methods relatively equal in execution time, and therefore the ultimate decision is preference of the coder?

    For 99% of what I do, clarity outweights performance considerations. So for clarity, I've adopted the following conventions:

    1. For object methods, always shift $self, and use array assignment to put any remaining arguments into variables. The shift becomes a visual clue that the sub is an object method.

    2. For constructors, I always shift the package name. If I'm interested in any additional arguments, I use array assignment to put them into variables. Typically, though, any arguments are a hash to initialize an instance.

    3. For non-object methods, use array assignment.

    This leads to code that looks like:

    sub new { my $pkg = shift; bless { default => 1, @_ }, $pkg; # @_ might override 'default' } sub method { my $self = shift; my($shoesize) = @_; .... } my non_method { my($height, $width) = @_; ... }
    Code that's consistently written is easier to read, and code that's easier to read is easier to optimize. YMMV, or course.

Re: Argument Passing, preference or performance ?
by tye (Sage) on Nov 11, 2002 at 21:34 UTC

    As I said in the CB when you asked, see Shift versus Sanity.

    "Performance"?? Why is that a concern??

            - tye (optimize only after profiling; profile only if needed)
Re: Argument Passing, preference or performance ?
by Wonko the sane (Deacon) on Nov 11, 2002 at 21:52 UTC
    I agree with tye, though personally I prefer to use the

    my ( $var_one, $var_two ) = @_;

    type syntax. I find it easier to read, takes up less space
    (hate scrolling continually just to see complete routine)
    and it leaves the initial arguement array untouched.

    Really just my personal preference,.. though intuition tells me that an array assignment
    would possibly be less resource intensive than a bunch of repeated shift calls.
    Though neither would probably make a big difference in your program.

    Your time would probably be better spend playing with Devel::Dprof
    and finding out what areas of your program really need to be optimized.

    Best Regards,
    Wonko

Re: Argument Passing, preference or performance ?
by Anonymous Monk on Nov 11, 2002 at 22:44 UTC
    Logically they are the same, and even the gracefulness are the same. However there is one situation, I would suggest to use @_ instead of shift, to provide the elegance. That's the time you pass named parms, for example:
    sub func { %parms = @_; foreach (keys %parms) { print "parms[$_] = $parms{$_}\n"; } } func("a" => 1, "b" => 2, "c" => 3);
    Well, you can use shift, but in this case, a little bit tasteless, is it?

      I disagree. I prefer passing named arguments as a hash reference:

      sub Open { my( $file, $opts )= @_; foreach $key ( %$opts ) { # ... } } Open( "file", { ReadOnly=>1, Retries=>2 } );
      for the following reasons:
      • It leaves lots of room for flexability in the API. For example, if my routine requires a 'file' parameter, then I don't see much point in requiring you to type File => when I can do things as above. You can even have optional parameters:
        sub Open { my $opts= UNIVERSAL::isa( $_[-1], "HASH" ) ? pop(@_) : {}; my( $file, $mode, $mask )= @_; # ... } Open( "file" ); Open( "file", { Exclusive=> 1 } ); Open( "file", "w", 0666, { Locked=>1 } );
      • The "Odd number of elements in hash assignment" warning automatically gets thrown at the calling code where it belongs
      • It provides a visual cue that named arguments are being used
      • It stops you from getting tricky and doing:     Create( Name=>"This", Users=>'fred','bob','joe' ); which you will regret later. Instead you are forced to:     Create( Name=>"This", Users=>['fred','bob','joe'] );
      But you need to be careful to not have your function modify the hash. (:

              - tye
      I'm not sure I agree that the gracefulness is the same. One situation that comes to mind is when you want to populate the elements of a hash with the passed arguments:
      sub add_person { my %person = (); @person{qw(firstname lastname addr1 addr2 city state zip)} = @_; ... }

      vs.

      sub add_person { my %person = (); $person{firstname} = shift; $person{lastname} = shift; $person{addr1} = shift; $person{addr2} = shift; $person{city} = shift; $person{state} = shift; $person{zip} = shift; ... }

      The first one just seems a lot cleaner to me. (Of course, in practice you might have the list of field names in a predefined array that you could loop through, but you get the idea.)

      --Kevin

      Logically they are the same

      Unfortunately not. routine1 makes the assignment without modifying @_, whereas routine2 consumes elements of @_. Add something like return $_[0]; to each of the above and in general you will get different results...

              $perlmonks{seattlejohn} = 'John Clyman';

Re: Argument Passing, preference or performance ?
by Ananda (Pilgrim) on Nov 12, 2002 at 11:00 UTC

    tye's got the reasoning, there is actually not much difference in the two methods, its better to use these methods for better readability.

    As far as performance is concerned it really doesnt matter.

    It is upto the coder to decide what/how to present by way of coding.

    Anandatirtha

Re: Argument Passing, preference or performance ?
by pg (Canon) on Nov 11, 2002 at 22:46 UTC
    (Forgot to login first, :-) Logically they are the same, and even the gracefulness are the same. However there is one situation, I would suggest to use @_ instead of shift, to provide the elegance. That's the time you pass named parms, for example:
    sub func { %parms = @_; foreach (keys %parms) { print "parms[$_] = $parms{$_}\n"; } } func("a" => 1, "b" => 2, "c" => 3);
    Well, you can use shift, but in this case, a little bit tasteless, is it?

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://212101]
Approved by VSarkiss
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others contemplating the Monastery: (3)
As of 2024-04-25 19:47 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found