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

Trying to understand subtleties of Getopt::Long, please help

by Rudif (Hermit)
on Sep 23, 2007 at 22:01 UTC ( [id://640616]=perlquestion: print w/replies, xml ) Need Help??

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

Hello monks

I am trying to understand the behavior of Getopt::Long::GetOptions(), in particulat what happens when user did not supply option values. Refering to my script below :

Cases 1..4 make sense.

Case 5, since the options are required ('='), why does GetOptions() return true? I expected it to fail.

Case 6, since the options are not required (':'), and the documentation says "In this case, if no suitable value is supplied, string valued options get an empty string '' assigned, while numeric options are set to 0.", I expected '' and 0 to be asigned to the variables.

In fact, behavior in cases 5 and 6 is same, while the documentation suggests to me that it would be different.

Can anyone clarify this ?

#!perl -w use strict; use Getopt::Long; use Data::Dumper; $Data::Dumper::Indent = 0; $|++; use Test::More tests => 12; # using scalars for options # The option name as specified to the GetOptions() function is called +the option specification. # Later we'll see that this specification can contain more than just t +he option name. # The reference to the variable is called the option destination. # Case 1 from module synopsis { my $data = "file.dat"; my $length = 24; my $verbose; my $result = GetOptions( "length=i" => \$length, # numeric "file=s" => \$data, # string "verbose" => \$verbose # flag ); ok($result); is( Data::Dumper->Dump( [ $data, $length, $verbose ], [qw / data l +ength verbose /] ), "\$data = 'file.dat';\$length = 24;\$verbose = undef;" ); } # For options that take values it must be specified whether the option + value is required or not, and what kind of value the option expects. # Three kinds of values are supported: integer numbers, floating point + numbers, and strings. # If the option value is required, Getopt::Long will take the command +line argument that follows the option and assign this to the option v +ariable. # If, however, the option value is specified as optional, this will on +ly be done if that value does not look like a valid command line opti +on itself. # Case 2 { @ARGV = (); my $tag = 'deftag'; # option variable with default value my $result = GetOptions( 'tag=s' => \$tag ); ok($result); is( Data::Dumper->Dump( [$tag], [qw / tag /] ), "\$tag = 'deftag'; +" ); } # Case 3 { @ARGV = ('--tag=MYTAG'); my $tag = 'deftag'; # option variable w +ith default value my $result = GetOptions( 'tag=s' => \$tag ); ok($result); is( Data::Dumper->Dump( [$tag], [qw / tag /] ), "\$tag = 'MYTAG';" + ); } # Case 4 { @ARGV = ('--bingo --tag=OTHERTAG'); my $tag = 'deftag'; # option variable w +ith default value my $result = GetOptions( 'tag=s' => \$tag ); ok( !$result ); is( Data::Dumper->Dump( [$tag], [qw / tag /] ), "\$tag = 'deftag'; +" ); } # In the option specification, the option name is followed by an equal +s sign = and the letter s. # The equals sign indicates that this option requires a value. # The letter s indicates that this value is an arbitrary string. # Other possible value types are i for integer values, and f for float +ing point values. # Using a colon : instead of the equals sign indicates that the option + value is optional. # In this case, if no suitable value is supplied, string valued option +s get an empty string '' assigned, while numeric options are set to 0 +. # Case 5 { @ARGV = (); my $tag; my $ival; my $result = GetOptions( 'tag:s' => \$tag, 'ival:i' => \$ival ); ok($result); is( Data::Dumper->Dump( [ $tag, $ival ], [qw / tag ival /] ), "\$t +ag = undef;\$ival = undef;" ); # why not a failure, ok(! $result); } # Case 6 { @ARGV = (); my $tag; my $ival; my $result = GetOptions( 'tag:s' => \$tag, 'ival:i' => \$ival ); ok($result); is( Data::Dumper->Dump( [ $tag, $ival ], [qw / tag ival /] ), "\$t +ag = undef;\$ival = undef;" ); # why not "\$tag = '';\$ival = 0;" } __END__
Rudif

Replies are listed 'Best First'.
Re: Trying to understand subtleties of Getopt::Long, please help
by ikegami (Patriarch) on Sep 23, 2007 at 22:18 UTC

    Case 5, since the options are required ('='), why does GetOptions() return true? I expected it to fail.

    You used : where you meant to use =, but that doesn't change the result.

    The *option's argument* is required, not the option itself.

    If you want to make the option required, you can check if the option variable is defined after the call to GetOptions.

    Case 6, since the options are not required (':'), and the documentation says "In this case, if no suitable value is supplied, string valued options get an empty string '' assigned, while numeric options are set to 0.", I expected '' and 0 to be asigned to the variables.

    It's a bit clearer in the documentation of for ":": "If [the option's argument] is omitted, an empty string will be assigned to string values options, and the value zero to numeric options."

    The following would be even clearer: "If the option is present but the the option's argument is omitted, an empty string will be assigned to string values options, and the value zero to numeric options."

    Since the option was never specified, its argument was never omitted, so the option variable was never assigned the default value.

    You can assign to the option variable before calling GetOptions to get the behaviour you desire.

    PS — It's safer to always localize changes to global variables. local @ARGV = ...;.

Re: Trying to understand subtleties of Getopt::Long, please help
by Joost (Canon) on Sep 23, 2007 at 22:19 UTC
    Re: case 5 and 6, AFAIK what is meant by "(not) optional" is that the values assigned to the arguments are (not) optional. In other words, the additional processing is only invoked if the arguments are specified.

    IOW: @ARGV = qw(--tag --ival) would be accepted for the ":" case, but not for the "=" case. And I note you specified ":" for both Case 5 & 6.

    I also find your usage of Data::Dumper incomprehensible. Since you're using Test::More, I would prefer the is_deeply method of comparing complex structure.

Re: Trying to understand subtleties of Getopt::Long, please help
by Sidhekin (Priest) on Sep 23, 2007 at 22:22 UTC

    What is "mandatory" and "optional" is not the option itself (options are by their nature always optional) but rather the associated argument.

    That is, --option without an argument will be an error on option=s or option=i, but will give the empty string on option:s and zero on option:i.

    (A missing --option or an option with argument (--option=42) will be treated the same by both.)

    Try @ARGV = qw( --tag ); with your cases 5 and 6, and you'll see the behaviour you expected.

    print "Just another Perl ${\(trickster and hacker)},"
    The Sidhekin proves Sidhe did it!

Re: Trying to understand subtleties of Getopt::Long, please help
by Rudif (Hermit) on Sep 24, 2007 at 20:44 UTC
    Thank you ikegami, Joost and Sidhekin

    The *option's argument* is required, not the option itself.

    What is "mandatory" and "optional" is not the option itself (options are by their nature always optional) but rather the associated argument.

    In other words, the additional processing is only invoked if the arguments are specified.

    Right, you clarified what was confusing me.

    I would prefer the is_deeply method of comparing complex structure.

    I agree, now that you mentioned it: easier to read, easier to update when developing the script.

    I also found an interesting discussion of its limitations and alternatives in Does Data::Dumper give you eye strain? Use Test::More::is_deeply() for debugging!

    The revised script below reflects the insights.

    Rudif

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://640616]
Approved by ww
Front-paged by naikonta
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others romping around the Monastery: (4)
As of 2024-03-29 15:02 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found