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

Is there a canonical practice for assigning value to an argument which, if "empty", is assigned a "default_value"? Here, "empty" is defined as an argument value which is either undef or the null string ('').

Notably, 0 (or perl false) is a valid, non-"empty" value, which rules out the construction $arg = (shift ||= 'default_value').

This is my current construction (note the use of the v5.10+ logical-or operator, //):

use 5.010; use strict; use warnings; sub f { # ( [$:arg] ) my $arg = do {$_ = shift // q{}; (length) ? $_ : 'default_value'}; $arg; } print f( )."\n"; # prints "default_value" print f( undef )."\n"; # prints "default_value" print f( q{} )."\n"; # prints "default_value" print f( 0 )."\n"; # prints "0" print f( 1 )."\n"; # prints "1" print f( 'value' )."\n"; # prints "value"

I don't want warnings or to duplicate the use of 'default_value'.

Is there a simpler / more elegant solution, say... without a named temporary variable?

A succinct solution which is functional back to earlier perl versions (5.6 or 5.8) would be a plus as well.

As always, your wisdom and opinions are appreciated.

Replies are listed 'Best First'.
Re: Assigning default values to function arguments which may be “empty”
by choroba (Cardinal) on Aug 17, 2016 at 19:33 UTC
    Checking the length is a common way. If you are concerned about a new variable, use the one Perl already created for you:
    sub f { length $_[0] ? $_[0] : 'default_value'; }

    ($q=q:Sq=~/;[c](.)(.)/;chr(-||-|5+lengthSq)`"S|oS2"`map{chr |+ord }map{substrSq`S_+|`|}3E|-|`7**2-3:)=~y+S|`+$1,++print+eval$q,q,a,
Re: Assigning default values to function arguments which may be “empty”
by stevieb (Canon) on Aug 17, 2016 at 19:43 UTC

    You can also used defined() directly:

    use warnings; use strict; print f() ."\n"; print f('hi') ."\n"; sub f { my $arg = defined $_[0] ? shift : 'default'; }

    output:

    default hi

      That doesn't cover his case for the empty string to also be defaulted; so:

      sub f { my $arg = defined $_[0] && length $_[0] ? shift : 'default'; }

      With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
      Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
      "Science is about questioning the status quo. Questioning authority". I knew I was on the right track :)
      In the absence of evidence, opinion is indistinguishable from prejudice.

        I'm experimenting with some variations based on ideas here and elsewhere (BTW, thanks for being so much friendlier than codereview.stackexchange.com! OMG, they are tightly wound).

        Thanks, again!

        d'oh! Yeah, I completely missed the whole empty thing.

Re: Assigning default values to function arguments which may be “empty”
by Anonymous Monk on Aug 18, 2016 at 06:18 UTC

    Like so?

    my ($arg) = grep length, shift, 'default';
    Or maybe so?
    my $grzblgh = sub { length or $_ = shift for shift }; sub f { (my $arg = shift)->$grzblgh("default"); }

      Esp. syntax #2 looks a little overcomplicated, why not:

      sub f { length or $_ = "default value" for my $var = shift; do_something_with($var); }
      But in my humble opinion I'd prefer for the sake of clarity:
      sub f { my $var = shift; for ( $var ) { last if length; $_ = $DEFAULT; } ... }

      I really like this answer. It prompted me to think more widely about the issue, looking at functions (built-ins and CORE modules) that might be helpful. This led to the construction that I'm now favoring:

      sub f { # ( [$:arg] ) use 5.007003; # perl v5.7.3; required for List::Util to be availab +le in CORE use List::Util qw/ first /; my $arg = first { defined && length } ( shift, 'default_value' ); $arg; }

        Why would you add a completely unnecessary dependency to do something more clearly and simply done using the base language; and pay a 100%+ performance penalty for the privilege?

        #! perl -slw use strict; use Benchmark qw[ cmpthese ]; sub f1 { # ( [$:arg] ) use 5.007003; # perl v5.7.3; required for List::Util to be availab +le in CORE use List::Util qw/ first /; my $arg = first { defined && length } ( shift, 'default_value' ); $arg; } sub f2 { my $arg = defined $_[0] && length $_[0] ? shift : 'default'; $arg; } our @args = ( undef, '', 'fred', 1, 1.5 ) x 1000; cmpthese -1, { stupid => q[ f1( $_ ) for @args ], simple => q[ f2( $_ ) for @args ], } __END__ C:\test>junk0 Rate stupid simple stupid 130/s -- -56% simple 294/s 127% --

        With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority". I knew I was on the right track :)
        In the absence of evidence, opinion is indistinguishable from prejudice.
        use 5.007003; # perl v5.7.3; required for List::Util to be available in CORE

        I must be missing something but I fail to see the advantage of this. You are deliberately disallowing users with perl 5.7.0 (say) the opportunity to run this script even if they have List::Util installed. Why would you do that?