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

Dear Perl Monks:

I have a subroutine named 'StartCapture' in which all parameters could be optional. If the user pass arguments to this subroutine it will be same as in the example specified below. If some arguments are not passed during function call then default values must be taken for those arguments ONLY.

How to achieve this in perl? Also, how to access the values of multi level hashes when receiving the arguments in subroutine 'StartCapture'

sub StartCapture { my %args = ( twigs => {filter => $filterTwigDefault, capture => $captureTw +igDefault}, hashes => {filter => %filterHashDefault, capture => %captureHa +shDefault}, files => {filter => 'fil_default.txt', capture => 'cap_defau +lt.txt'}, results => 'c:/SomeDefault.txt', @_ ); print "results => $args{results}"; } StartCapture( { twigs => {filter => $filterTwig, capture => $captur +eTwig}, hashes => {filter => %filterHash, capture => %captur +eHash}, files => {filter => 'filter.txt', capture => 'captur +e.txt'}, results => 'c:/temp.txt' } );
Thanks in advance! Your input is much appreciated!

Replies are listed 'Best First'.
Re: Optional and default parameters for a subroutine
by friedo (Prior) on Aug 29, 2005 at 19:47 UTC
    It looks like you've already got the the optional arguments handled correctly in your subroutine, but you're passing it a hash reference where it expects a plain list. Change your subroutine invocation to:

    StartCapture( twigs => {filter => $filterTwig, capture => $captureTwig}, hashes => {filter => \%filterHash, capture => \%captureHash}, files => {filter => 'filter.txt', capture => 'capture.txt'}, results => 'c:/temp.txt' );

    Notice that I also changed %captureHash and %filterHash to \%captureHash and \%filterHash so they are passed as references instead of flattening into lists.

    To access nested elements, you can do something like $args{twigs}{filter}. For more, see perlreftut and perldsc.

      I didn't notice that I passed a hash referece..Thanks for pointing out the mistake!
      Your code works! Thanks once again.
Re: Optional and default parameters for a subroutine
by saberworks (Curate) on Aug 29, 2005 at 20:03 UTC
    Maybe I'm missing something crucial here, but I've always liked the simplified:

    sub my_function { my %args = @_; # Now take care of default arguments... $args{arg1} ||= 'default value1'; $args{arg2} ||= 'default value2'; }

    It basically evaluates $args{arg1}, and if it evaluates to true, they must have passed it, otherwise, assign the default value.

      But as you noted, that will only work if your arguments are always true, or that false indicates "default value". The nice thing about using the %hash = ( default => "value", @_ ); construct (besides being shorter) is that it works for all values.

      To do the same with explicit testing you'd need

      $args{arg1} = 'default value1' unless exists $args{arg1};
        Although I wrote the phrase, "if it evaluates to true," I didn't consider its implications. Thanks for pointing that out.
Re: Optional and default parameters for a subroutine
by Joost (Canon) on Aug 29, 2005 at 20:03 UTC
    I have a subroutine named 'StartCapture' in which all parameters could be optional. If the user pass arguments to this subroutine it will be same as in the example specified below. If some arguments are not passed during function call then default values must be taken for those arguments ONLY.
    That's what your code does already. (update/note: but see also friedo's post on the \%filterHash change).
    Also, how to access the values of multi level hashes when receiving the arguments in subroutine 'StartCapture'
    my $value = $args{twigs}{filter};
    for example. See perldata and perlreftut.