Re: Using a 'getopt' in module code
by brian_d_foy (Abbot) on Dec 04, 2006 at 16:16 UTC
|
If you're up to 13 options, and most of them are not used together, its time to be nice to the users by providing a higher level interface to function that takes care of most of those details. You can curry the function.
Each wrapper function represents a particular way of calling the general function so the programmer doesn't have to know about all of the other options. They just know what they want to acccomplish and the wrapper function takes care of the other details. If you change the general function, the programmer doesn't really care as long as the wrapper functions still do their work correctly.
sub general_function_with_lots_of_args { ... }
sub do_it_with_name {
general_function_with_lots_of_args( undef, undef, $_[0], undef, ..
+. )
}
sub do_it_using_id {
general_function_with_lots_of_args( undef, $_[0], undef, ... )
}
sub do_it_this_way { ... }
sub do_it_that_way { ... }
As for the various Getopt modules, there are indeed quite a few. However, there are quite a few ways that programs take command line arguments too. I talk about some of these in my configuration chapter in Mastering Perl.
| [reply] [d/l] |
|
|
| [reply] |
Re: Using a 'getopt' in module code
by Fletch (Bishop) on Dec 04, 2006 at 15:58 UTC
|
Aside from the fact that getopts is going to try and read from @ARGV and not @_, the usual means of getting keyword-y arguments for subroutines is to use @_ to initialize a hash.
sub blortz {
my @defaults = qw( foo 1 baz 42 );
my %args = ( @defaults, @_ );
print "baz is the answer\n" if $args{baz} == 42;
}
blortz( baz => 2.71828 );
| [reply] [d/l] [select] |
Re: Using a 'getopt' in module code
by davorg (Chancellor) on Dec 04, 2006 at 15:59 UTC
|
Getopt works on @ARGV, so you can't use it to process function arguments. Well, not without doing @ARGV = @_ which might well break other stuff.
In situations like this, most people would probably pass the function arguments as a hash.
my_func(foo => 1, bar => 2);
sub my_func {
my %args = @_;
if ($args{foo}) {
...
}
# etc...
}
--
< http://dave.org.uk>
"The first rule of Perl club is you do not talk about
Perl club." -- Chip Salzenberg
| [reply] [d/l] |
|
|
#!/usr/bin/perl
use strict;
use warnings;
use Getopt::Std;
use Data::Dumper;
sub getopt_fun {
my %args;
{
local @ARGV = @_;
getopt 't', \%args;
}
print Dumper \%args;
}
getopt_fun (-t => 'foo');
Edit: narrowed the scope of the local.
| [reply] [d/l] |
Re: Using a 'getopt' in module code
by ikegami (Patriarch) on Dec 04, 2006 at 17:17 UTC
|
Yet another method is to use a callback. For example,
mysort(\@list, 'age', 'asc', 'name', 'asc');
can be replaced with
mysort(sub { $_[0]{age} <=> $_[1]{age}
|| $_[0]{name} cmp $_[1]{name} }, @list);
With the right prototype (mysort (&@) { ... }), the above can also be written as
mysort { $_[0]{age} <=> $_[1]{age}
|| $_[0]{name} cmp $_[1]{name} } @list;
I haven't read it, but I believe the book "Higher Order Perl" has a lot on this subject.
| [reply] [d/l] [select] |
Re: Using a 'getopt' in module code
by Firefly258 (Beadle) on Dec 04, 2006 at 16:22 UTC
|
Why don't you rewrite the subroutine to take named parameters as a hash like so?
sub func {
my %args = (
# default options
option1 => "Foo",
option2 => "Bar",
@_, # passed options
);
if ($args{option1}) { ... }
if ($args{option2}) { ... }
}
func(option1 => "Foozball", option2 => "Barracuda");
perl -e '$,=$",$_=(split/\W/,$^X)[y[eval]]]+--$_],print+just,another,split,hack'er
| [reply] [d/l] [select] |
Re: Using a 'getopt' in module code
by djp (Hermit) on Dec 05, 2006 at 03:15 UTC
|
| [reply] |
Re: Using a 'getopt' in module code
by Anonymous Monk on Dec 04, 2006 at 23:23 UTC
|
Just to be safe, I'm going to post this as AM.
I work with a set of Perl libraries that were designed to use Getopt::Long as the standard parameter-passing mechanism. (Oddly, only with single letter variants.)
Among the many things that sucks about this are:
- You cannot pass nested structures, callbacks, references. Objects. Filehandles. Anything but a string. You might not want that now, but trust me, having a OO framework where methods can't take references is suck.
- All strings are copied many times... normally into an "-i$num" string before passing, then on to the stack, then into @ARGV, then into getopt, then into a destination variable. When passing large buffers into methods, this is suck.
- All numeric arguments are cast to opt-prefixed strings, then back to numbers. This is especially suck if you happen to like retaining floating point accuracy.
At one point I had a longer list. It just made me sad, though. Don't do it. Your code maintainers will loath you.
| [reply] [d/l] [select] |
Re: Using a 'getopt' in module code
by slloyd (Hermit) on Dec 05, 2006 at 00:11 UTC
|
I suggest you pass in a hash instead of a simple array so that your arguements do not have to be numbered.
if(myfunction(debug=>1,var=>$val)){...}
sub myfunction{
my @params=@_;
if($params{debug}){...}
}
| [reply] [d/l] |
Re: Using a 'getopt' in module code
by revence27 (Novice) on Dec 05, 2006 at 08:42 UTC
|
| [reply] [d/l] [select] |
Re: Using a 'getopt' in module code
by nacredata (Sexton) on Dec 06, 2006 at 05:50 UTC
|
How about using the trick of passing in a reference to a hash to hold the arguments?
http://www.oreilly.com/catalog/perlbp/chapter/ch09.pdf | [reply] |