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

Bonjour Monks,

I have an optimization/minimum typing question. I wonder what the best and/or shortest method is for assigning default values to variables. For example, a typical subroutine call for me looks like:

use vars qw($VAR2); # global defaults and whatnot $VAR2 = 'thingamabob'; sub routine { my $input_ref = {@_}; my $var1 = $input_ref->{var1} || ''; my $var2 = $input_ref->{var2} || $VAR2; ...etc... }

This seems to work fairly well for me, however, it doesn't allow me create subroutine boolean flag called "do_this" that defaults to true, but the user can explicitly set false, eg:

sub routine { my $input_ref = {@_}; my $do_this = $input_ref->{do_this} || 1; }

If the user calles routine( do_this => 0 ), do_this will, obviously still be true. Now, I know how to code around this with:

my $do_this = 0; if ($input_ref->{do_this} eq '0') { $do_this = 0 } else { $do_this = 1 };

But that seems a little long winded. I was wondering if the Monks had any input (ha!) on this, or if my whole default assignment strategy is misguided.

Thanks,
Justin

Replies are listed 'Best First'.
Re: Best method of assigning "default" values?
by Transient (Hermit) on Jun 28, 2005 at 15:46 UTC
    How about defined?

    my $val = defined($input_ref->{do_this}) ? $input_ref->{do_this} : "My + Default Value";
    Of course, some monk more clever than I will figure out a way to shorten it ;)
      exists might be preferable to definded if you want to distinguish the case of routine( do_this => undef ).
      OP -- There was also a very closely related discussion yesterday/this morning in the Hashes and keys... thread.
Re: Best method of assigning "default" values?
by Mutant (Priest) on Jun 28, 2005 at 16:41 UTC
    I've heard a future version of Perl (5.10.x ?) is going to have a new operator that assigns if undefined, ie.
    my $foo ||= 1; # $foo is set to '1' if it was previously a false value my $bar //= 1; # $bar is set to '1' only if it was undefined (0 and em +pty string don't count).
    It would also be useful to have // (or equivilent) as a normal short circuit operator as well, although this is really syntactic sugar for defined and existing operators.

    In the meain time, personally, I would use:
    sub routine { my $input_ref = {@_}; my $var1 = defined $input_ref->{var1} ? $input_ref->{var1} : + 1; }
    Not quite as pretty, but better than a full if block.

      Also, I believe Perl6 already has the //= operator, as well.

          -Bryan

Re: Best method of assigning "default" values?
by ikegami (Patriarch) on Jun 28, 2005 at 15:56 UTC

    I'm going to broaden the topic to positional arguments for future reference. For positional arugments, the equivalent of exists that davidrw suggested for hashes would be to check the size of @_.

    sub my_sub { my ($arg1, $arg2, $opt_arg1, $opt_arg2) = @_; $opt_arg1 = default if @_ < 3; $opt_arg2 = default if @_ < 4; ... }

    That allows all false values to be specified, including undef.

Use Params::Validate or a similar module
by rrwo (Friar) on Jun 29, 2005 at 10:16 UTC

    I would take a look at Params::Validate, Params::Smart (shameless plug ;) or one of the many other Params::* modules to do the work of setting default values as well as validating then.

Re: Best method of assigning "default" values?
by Zaxo (Archbishop) on Jun 29, 2005 at 03:20 UTC

    Yet another way, set up defaults when you construct the hash,

    sub routine { my $input_ref = { var1 => '', var2 => $VAR2, # . . . @_ }; my $var1 = $input_ref->{var1}; my $var2 = $input_ref->{var2}; # ...etc... }
    That way your defaults are in the hash to start with, and can be overridden by anything the user wants to assign. Less logic to go wrong.

    After Compline,
    Zaxo