HiveBrain v1.2.0
Get Started
← Back to all entries
patternMinor

Assigning default values to function arguments which may be "empty"

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
argumentsmaywhichfunctionemptydefaultvaluesassigning

Problem

In perl, is there a canonical practice or idiom 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 $min_perl_version = (shift ||= '5.008009').

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

my $min_perl_version = do {$_ = shift // q{}; (length) ? $_ : '5.008009'};


as in the example function:

sub is_CORE { # ( $:MIN_PERL_VERSION , $:MODULE )
    use 5.008009; # perl v5.8.9; required for Module::CoreList to be available in CORE
    my $min_perl_version = do {$_ = shift // q{}; (length) ? $_ : '5.008009'}; # "empty" => default to version 5.008009
    my $module = shift;
    return ($Module::CoreList::VERSION >= 2.99) && Module::CoreList::is_core($module, undef, $min_perl_version);
}


I don't want warnings or to duplicate the use of the 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.

edit: for clarity

For clarification, the function interface and definition of argument validity (eg, what "empty" means) are set constants. While I appreciate any critique, a conversation about the line:

my $min_perl_version = do {$_ = shift // q{}; (length) ? $_ : '5.008009'};


and how it might be better coded is the real point of the question.

Solution

use 5.008009 is insufficient here, since you're using the // operator, which was introduced in Perl 5.10.

This function feels awkwardly designed. Generally, parameters that have default values appear after all required parameters. Here, I would need to explicitly pass in undef as the first parameter to take advantage of the default. Also note that the parameters for your is_CORE are backwards relative to Module::CoreList::is_core.

I also don't understand the benefit of having the empty string trigger the default. I can understand having undef trigger the default. I could also agree with having all "falsy" values trigger the default. But this particular design feels weird. If I had to do it, though, I'd write it like this:

sub is_CORE {
    use 5.008009; # perl v5.8.9; required for Module::CoreList to be available in CORE
    my ($module, $min_perl_version) = @_;
    $min_perl_version = '5.008009' unless defined $min_perl_version && length $min_perl_version;
    $Module::CoreList::VERSION >= 2.99 && Module::CoreList::is_core($module, undef, $min_perl_version);
}

Code Snippets

sub is_CORE {
    use 5.008009; # perl v5.8.9; required for Module::CoreList to be available in CORE
    my ($module, $min_perl_version) = @_;
    $min_perl_version = '5.008009' unless defined $min_perl_version && length $min_perl_version;
    $Module::CoreList::VERSION >= 2.99 && Module::CoreList::is_core($module, undef, $min_perl_version);
}

Context

StackExchange Code Review Q#138969, answer score: 4

Revisions (0)

No revisions yet.