Beefy Boxes and Bandwidth Generously Provided by pair Networks
We don't bite newbies here... much

Reduce Redundant Repetition

by ybiC (Prior)
on Jan 21, 2002 at 21:18 UTC ( #140434=perlquestion: print w/replies, xml ) Need Help??

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

The following chunk facilitates default values for command-line arguments.   It works fine, but I suspect there's a less redundant approach than just repeating "if defined($opt_foo){$foo=$opt_foo} else {$foo=def_val}" for seven different values of "foo".   I'd use hash keys and values, but there are three unique parameters for each iteration.

Suggestions, o wise brethren and sistren?

#!/usr/bin/perl -w use strict; use Getopt::Long my ( $targ, $opt_targ, $firstport, $opt_firstport, $lastport, $opt_lastport, $proto, $opt_proto, $udptimeout, $opt_udptimeout, $contimeout, $opt_contimeout, $help, ); GetOptions( 'targ=s' => \$opt_targ, 'firstport=s' => \$opt_firstport, 'lastport=s' => \$opt_lastport, 'proto=s' => \$opt_proto, 'udptimeout=s' => \$opt_udptimeout, 'contimeout=s' => \$opt_contimeout, 'help!' => \$opt_help, ); if (defined $opt_targ){ $targ = $opt_targ } else {$targ='localhost';} if (defined $opt_firstport){ $firstport = $opt_firstport } else {$firstport=1;} if (defined $opt_lastport){ $lastport = $opt_lastport } else {$lastport=1024;} if (defined $opt_proto){ $proto = $opt_proto} else {$proto='tcp';} if (defined $opt_udptimeout){ $udptimeout = $opt_udptimeout } else {$udptimeout=3;} if (defined $opt_contimeout){ $contimeout = $opt_contimeout } else {$contimeout=3;} if (defined $opt_help){ Usage('You rang, sir?'); exit; }

    striving toward Perl Adept
    (it's pronounced "why-bick")

Replies are listed 'Best First'.
(jcwren) Re: Reduce Redundant Repetition
by jcwren (Prior) on Jan 21, 2002 at 21:21 UTC

    How about:

    $proto = defined $opt_proto ? $opt_proto : 'tcp'

    Personally, though, I'd go for putting all your arguments in a hash, with a reference to the opt_arg value, the variable you want the final result in, and the default value, and use a for loop to rip through them setting them all. Perhaps include a type (numeric, string, flag) and do a little type checking. For instance, if someone passed '123' to the $opt_tcp value, it prolly ain't gonna work...


    e-mail jcwren

Re: Reduce Redundant Repetition
by kal (Hermit) on Jan 21, 2002 at 21:38 UTC

    There are a number of ways to reduce some of this. The easiest way to get rid of the if's is probably something like:

    $contimeout = $opt_contimeout || 3;

    Another simple way of setting defaults is to set them up before using Getopt::Long:

    #!/usr/bin/perl -w use strict; use Getopt::Long; my ($lines, $cols) = (5, 16); GetOptions ('line=s' => \$lines, 'col=s' => \$cols); print "Lines: $lines Cols: $cols\n";

    A very simple example I know, but it illustrates the point :)

    Update: jcwren pointed out that I failed to mention this has a potential failure if you use '||' - if you want to set a value to '0', you won't be able to unless the default is also '0'. I advise pre-setting the defaults, and then letting the user override them - much simpler :) Thanks, jcwren.

(tye)Re: Reduce Redundant Repetition
by tye (Sage) on Jan 21, 2002 at 22:08 UTC
Re: Reduce Redundant Repetition (Rus: use ternaries)
by Russ (Deacon) on Jan 22, 2002 at 00:08 UTC
    I don't see anyone using the ternary operator...
    $targ = defined $opt_targ ? $opt_targ : 'localhost'; $firstport = defined $opt_firstport ? $opt_firstport : 1; $lastport = defined $opt_lastport ? $opt_lastport : 1024; $proto = defined $opt_proto ? $opt_proto : 'tcp'; $udptimeout = defined $opt_udptimeout ? $opt_udptimeout : 3; $contimeout = defined $opt_contimeout ? $opt_contimeout : 3; Usage('<lurch>You rang?</lurch>'), exit if defined $opt_help;
    And it still works with valid zero values.


Re: Reduce Redundant Repetition
by mrbbking (Hermit) on Jan 21, 2002 at 23:15 UTC
    You might consider replacing something like this...
    if (defined $opt_targ){ $targ = $opt_targ } else {$targ='localhost';}
    with something like this...
    $targ = $opt_arg; $targ ||= 'localhost';
    ...following the "this breaks if zero is an acceptable value" admonition previously stated above...
Re: Reduce Redundant Repetition
by Aristotle (Chancellor) on Jan 22, 2002 at 03:27 UTC
    A demonstration is better than many words:
    #!/usr/bin/perl -w use strict; use Getopt::Long; my $targ = 'localhost'; my $firstport = 1; my $lastport = 1024; my $proto = 'tcp'; my $udptimeout = 3; my $contimeout = 3; { my %options; GetOptions(\%options, qw(targ=s firstport=s lastport=s proto=s udpti +meout=s contimeout=s help!)); if (defined $options{help}){ Usage('You rang, sir?'); exit; } ($targ, $firstport, $lastport, $proto, $udptimeout, $contimeout) = @options{qw(targ firstport lastport proto udptimeout contimeout)}; }

    With some further generalization the variable-/option-names wouldn't have to appear four times each as in this code either.

    Update: maybe you want qw(targ=s firstport=s lastport=s proto=s udptimeout=i contimeout=i help!)? I can see someone saying POP3 for the port f.ex - but it doesn't seem to make any sense to take arbitrary values for the timeout parameters.

    Makeshifts last the longest.

Log In?

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

How do I use this? | Other CB clients
Other Users?
Others taking refuge in the Monastery: (5)
As of 2021-10-20 14:50 GMT
Find Nodes?
    Voting Booth?
    My first memorable Perl project was:

    Results (81 votes). Check out past polls.