Beefy Boxes and Bandwidth Generously Provided by pair Networks
Problems? Is your data what you think it is?

Setting defaults in subroutines

by rbi (Monk)
on Aug 04, 2004 at 09:34 UTC ( #379944=perlquestion: print w/replies, xml ) Need Help??
rbi has asked for the wisdom of the Perl Monks concerning the following question:

Hi, could somebody explain me why || and or have a different behaviour as in the example below ? Thank you very much.
use strict; use warnings; use Data::Dumper; my @array = (1,2,3,4); my @index = (1,3); &these(Index=>\@index); &those(Index=>\@index); sub these { my %args = @_; my @index = @{$args{Index}} || (); my $dump = Dumper($args{Index}); print "$dump"; $dump = Dumper(\@index); print "$dump"; } sub those { my %args = @_; my @index = @{$args{Index}} or (); my $dump = Dumper($args{Index}); print "$dump"; $dump = Dumper(\@index); print "$dump"; }

Replies are listed 'Best First'.
Re: Setting defaults in subroutines
by davorg (Chancellor) on Aug 04, 2004 at 09:43 UTC

    You're being burnt by a combination of operator precedence and context.

    my @index = @{$args{Index}} || ();

    is interpreted as

    my @index = (@{$args{Index}} || ());

    Then the || operator forces scalar context on @{$args{Index}} which therefore gives the number of elements in the array (which is 2).

    On the other hand,

    my @index = @{$args{Index}} or ();
    is interpreted as
    (my @index = @{$args{Index}}) or ();

    So the array is evaluated in list context and everything works as expected.


    "The first rule of Perl club is you do not talk about Perl club."
    -- Chip Salzenberg

      Pretty clear explaination. Thank you very much!
        The best way to see the precedence is to have a look at the cheat sheet, which shows this. I got confused with this myself a couple a weeks ago.

Re: Setting defaults in subroutines
by PodMaster (Abbot) on Aug 04, 2004 at 09:45 UTC
    `perldoc perlop'
    C:\>perl -MO=Deparse,-p -e"die $a or $b" (die($a) or $b); -e syntax OK C:\>perl -MO=Deparse,-p -e"die $a || $b" die(($a || $b)); -e syntax OK C:\>

    MJD says "you can't just make shit up and expect the computer to know what you mean, retardo!"
    I run a Win32 PPM repository for perl 5.6.x and 5.8.x -- I take requests (README).
    ** The third rule of perl club is a statement of fact: pod is sexy.

Re: Setting defaults in subroutines
by hv (Parson) on Aug 04, 2004 at 11:02 UTC

    Further to davorg's explanation, my usual idiom for getting the desired result is to move the default into the dereference:

    my @index = @{ $args{Index} || [] };

    This sidesteps the problem of @array || something forcing the array into scalar context, and also permits an undefined value.


      I agree. The best way to clarify your test and sidestep the precedence issue is to use parenthesis to explicitly describe how your test should be evaluated.
Re: Setting defaults in subroutines
by Fletch (Chancellor) on Aug 04, 2004 at 13:02 UTC

    Rather than setting %args from @_ and then adding in defaults, I tend to use something along the lines of:

    sub foo { my @defaults = ( Index => [], weeble => "floop", ); my %args = ( @defaults, @_ ); for( @{ $args{ Index } } ) { ## ... } }

    You might also want to check out Params::Validate, which provides checking of parameters and allows you to specify default values where required.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://379944]
Approved by Corion
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others exploiting the Monastery: (3)
As of 2016-09-29 04:22 GMT
Find Nodes?
    Voting Booth?
    Extraterrestrials haven't visited the Earth yet because:

    Results (547 votes). Check out past polls.