in reply to Referencing built-ins
(I didn't know you were subscribed to paris-pm-list :)
It wasn't just "someone", it was Rafael Garcia-Suarez, p5p summarizer for the rest of us mere mortals who can't keep up with p5p.
The rest of the thread was interesting too, and adds context to what's being discussed here.
It started out when a person who had use strict enabled wondered why the following code didn't work (it complains about $opt_h being undefined):
getopts("hf:d:") || die HELP(); if ($opt_h) { HELP(); }
A couple people pointed out that an alternative consists of passing getopts a reference to a hash, which sidesteps the issue.
To get the code to work as advertised you need to predefine some package variables, such as with
use vars qw/$opt_h $opt_f $opt_d/;
I personally took/take issue with using the hash approach, because if you screw up your keys, Perl will obligingly autovivify them for you. I once spent far too long tracing down a bug because I missed this fact. I was staring at code that should have been executed, but it wasn't, because the condition was if( $opt{t} ) instead of if( $opt{T} ) or something along those lines.
These days I prefer to encapsulate that stuff so that the compiler will grunt at compile time if I make a misteak:
{ my %opt; getopts("hf:d:") || die HELP(); sub opt_h { exists $opt{h} ? 1 : 0 } sub opt_f { exists $opt{f} ? 1 : 0 } sub opt_d { exists $opt{d} ? 1 : 0 } } if( opt_h ) { ... } if( opt_j ) { # compile time error ... }
<update>
And graff is correct about how to deal with options that have values. You can add all sorts of functionality in those subs. You can even stick prints in them to find out where in a twisty maze of code they get called :)
In this particular instance (I didn't play close enough attention to the getopt spec in the OP; what you see is a cut and paste error) would be something more like:
sub opt_f { if( not exists $opt{f} ) { 0 } elsif( not defined $opt{f} ) { 'default-value' } else { $opt{f} } }
The idea being that you never return undef, and you return different things according to whether the switch was not specified, or specified with(out)? an optional value.
</update>
What is more, %opt is now hidden. You can no longer accidently stomp on it and accidently change the directives your program is supposed to follow. I've done that too in my time.
Rafael's reply is to be taken within the context of that code snippet. Personally I think it's interesting that Perl allows that, however, I can't help but feel that it's not overly useful, because it buries the declaration deep inside a statement, and it might be hard for someone to spot.
As it is, the following still gives me the willies:
(my $new = $old) =~ s/foo/bar/;
I can't help thinking that $new is suddenly going to go out of scope outside the parentheses. I know it won't, and I use this idiom frequently, but I don't think I'll ever be truly satisfied with it. That said, I like the functionality, I just think it's a reflection on the botched state of precedence rules.
_____________________________________________
Come to YAPC::Europe 2003 in Paris, 23-25 July 2003.
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re: A better usage of getopts
by graff (Chancellor) on Apr 09, 2003 at 00:33 UTC | |
|
Re^2: Referencing built-ins
by Aristotle (Chancellor) on Apr 09, 2003 at 09:59 UTC |