Re: Getopt::Long wishes (was: RFC: Getopt::Modern)
As I've said before, if GetOptions() could be a few-lines wrapper around the $opt = Getopt::Long-new()... $opt-get([EMAIL PROTECTED]) dance, this allows the author (of what will most likely be a module if they want to parse something besides ARGV) to design their own entry point if need be. I'm puzzled. Basically, you suggest that it is okay to craft your own entry point sub MyGetOptions {# [EMAIL PROTECTED], @opts my $argv = shift; Getopt::Long-new(@_)-get($argv); } while you always disapproved of something like sub MyGetOptions {# [EMAIL PROTECTED], @opts local(@ARGV) = @{shift}; GetOptions(@_); } There's not a lot of reason to add new functionality into the old interface because anybody using the new functionality (by definition) requires the new version. I can fully agree with that. -- Johan
Re: Getopt::Long wishes (was: RFC: Getopt::Modern)
# The following was supposedly scribed by # Johan Vromans # on Saturday 09 July 2005 02:58 am: this allows the author (of what will most likely be a module if they want to parse something besides ARGV) to design their own entry point if need be. I'm puzzled. Basically, you suggest that it is okay to craft your own entry point Right. But this example is too simplistic to show why using an object and breaking the functionality into method calls is worthwhile. In this simple case, neither approach comes out ahead. sub MyGetOptions {# [EMAIL PROTECTED], @opts my $argv = shift; Getopt::Long-new(@_)-get($argv); } while you always disapproved of something like sub MyGetOptions {# [EMAIL PROTECTED], @opts local(@ARGV) = @{shift}; GetOptions(@_); } Unless you assign points to clarity. Even though GetOptions is documented to work on @ARGV, I have to *know* that. This is one more thing in my head instead of on the screen right in front of me. It's sort of a distant GOTO that documentation. I wouldn't GOTO a label in another module, why would it be acceptable if it's a virtual GOTO that involves perldoc? Don't try to find too much in my objection to local(@ARGV) = shift when considering it in isolation. This is just one facet of what I think could be improved with a step back and a hard look at the overall architecture. In Getopt::Crazy, I made GetOptions() operate on @ARGV, because that is the intended use of that function: It parses *the* command-line arguments. When we leave that usage paradigm, suddenly we're breaking the rules of good design because there's a logic speed-bump in the middle of our code: Why is this local() here? Oh! Right. GetOptions() isn't meant to be used like this. (Repeat each time you read the code.) The more complicated examples better illustrate the advantage of using objects and methods. ... $first_pass = Getopt::Long-create(%args); $next_pass = Getopt::Long-create(\%config, %conf_args); $first_pass-get([EMAIL PROTECTED], {pass_these = [$next_pass]}) or croak first pass failed; $next_pass-get([EMAIL PROTECTED]) or croak config pass failed; foreach my $remainder (@arglist) { ... } ... The above might be in main::, but: 1. might also be somewhere in a package like Getopt::Helpful (which needs a finer-grained access to the configuration to cleanly abstract the getopt problem while combining it with the config and documentation) 2. might be in some other module (ala Tk::*) that just wants to provide an API with position-independent parameters mixed with list items 3. might be in some application which I have not yet imagined (and therefore I cannot make too many assumptions about its needs) IMO, the need to do something like getopt() happens so often that it is almost like a builtin (i.e. It is an aspect of the language.) The power of Perl does not come so much from the fact that we *can* accomplish something but from how succinctly we can express it. Some have said that every point I've raised can be filed under hard things possible, but I'm seeing patterns in my code and thinking that it should be simpler. For the sake of convenience, we've been discussing rather basic examples and I am partly at fault for not showing enough code to back-up my English (maybe a rewrite of Randy's Scratchpad.pm would provide a complex enough example?) The trick with redesigning an architecture is that you have to consider the combination of all of these simple issues. --Eric -- Peer's Law: The solution to the problem changes the problem. - http://scratchcomputing.com -
Re: Getopt::Long wishes (was: RFC: Getopt::Modern)
[EMAIL PROTECTED] (Johan Vromans) writes: [Quoting Sam Vilain, on June 27 2005, 22:56, in Re: Getopt::Long wis] If passing an array ref first doesn't interfere with the calling convention, then imho you don't need to change the function name. Interfere? No, but elegant? Currently, GetOptions allows an array ref as the first argument (to fetch the options from), but it also allows a hash ref as the first argument (to store the options in), while the first argument may also be something typical non-option to designate a different option starter string. For the programmer, there's a very definite order in these 'first' arguments, but I doubt the ordinary (or casual) user will find this easy. Despite this, I now strongly lean towards _not_ creating an additional entry point for this functionality. While GetOptionsFromArray seems nice, there's also a reason for GetOptionsToHash, GetOptionsWithNonStandardIntroducer and so on. This would make code and maintenance unneccessarily complex. So my proposal: * Entry point remains GetOptions * First argument may be an array ref - array to parse options from * First (or next) argument may be a hash ref - hash to put option values in * First (or next) argument, if scalar and not a valid option, may introduce non-standard option introducers. -- Johan
Re: Getopt::Long wishes (was: RFC: Getopt::Modern)
On Jul 5, 2005, at 4:44 AM, Johan Vromans wrote: ... I now strongly lean towards _not_ creating an additional entry point for this functionality. While GetOptionsFromArray seems nice, there's also a reason for GetOptionsToHash, GetOptionsWithNonStandardIntroducer and so on. This would make code and maintenance unneccessarily complex. You could easily add a method that accepted named parameters instead of positional (which IMO would improve readability a lot): GetOptions(from = [EMAIL PROTECTED], described_by = [length=i, file=s, verbose], to = \%args, ...); IMO that's usually the right way to make the interface when there are lots of different orthogonal options that the caller might want to employ. How you name the parameters would be up to you, of course. -Ken
Re: Getopt::Long wishes (was: RFC: Getopt::Modern)
[Quoting Sam Vilain, on June 27 2005, 11:35, in Re: Getopt::Long wis] Johan Vromans wrote: You mean, you are going to pass things like STDOUT, STDERR, ENV and so on, to every function that may use them? [1] Global things are intended to be global, I'd say. This is why code using CGI.pm is so hard to wrap, too. Assumptions that globals will always be globals. Then you go and try and do anything vaguely re-entrant and it all falls to pieces. I think there's a fundamental difference between user variables that are used globally (which, indeed, expose the problem you mentioned) and variables that are global by design, like STDOUT and ARGV. Anyway, the next version of Getopt::Long will have the ability to use an arbitrary array instead of ARGV. Now, do you want this to be yet another if the first argument is an array reference ... or yet another :config option? -- Johan
RE: Getopt::Long wishes (was: RFC: Getopt::Modern)
Title: RE: Getopt::Long wishes (was: RFC: Getopt::Modern) [EMAIL PROTECTED] wrote on Monday, June 27, 2005 9:46 AM Anyway, the next version of Getopt::Long will have the ability to use an arbitrary array instead of ARGV. Now, do you want this to be yet another if the first argument is an array reference ... or yet another :config option? Imo it would better to expose a different subroutine name for this. Ie: sub GetOptions { GetOptionsArray([EMAIL PROTECTED],@_); } Is that ruled out for some reason? Yves
Re: Getopt::Long wishes (was: RFC: Getopt::Modern)
[Quoting Orton, Yves, on June 27 2005, 10:17, in RE: Getopt::Long wis] sub GetOptions { GetOptionsArray([EMAIL PROTECTED],@_); } GetOptionsFromArray? -- Johan
Re: Getopt::Long wishes (was: RFC: Getopt::Modern)
Orton, Yves wrote: Imo it would better to expose a different subroutine name for this. sub GetOptions { GetOptionsArray([EMAIL PROTECTED],@_); } Is that ruled out for some reason? If you consider the signature a part of the subroutine name, then simply making it take an arrayref as the first argument is enough to distinguish it. in Perl 6 you could say multi sub GetOptions(Array @ARGV, Pair [EMAIL PROTECTED]) { ... } is a different subroutine to multi sub GetOptions(Pair [EMAIL PROTECTED]) { ... } If passing an array ref first doesn't interfere with the calling convention, then imho you don't need to change the function name. But that, of course, is a matter of style ;-) Sam.
Re: Getopt::Long wishes (was: RFC: Getopt::Modern)
[Quoting Sam Vilain, on June 27 2005, 22:56, in Re: Getopt::Long wis] If passing an array ref first doesn't interfere with the calling convention, then imho you don't need to change the function name. Interfere? No, but elegant? Currently, GetOptions allows an array ref as the first argument (to fetch the options from), but it also allows a hash ref as the first argument (to store the options in), while the first argument may also be something typical non-option to designate a different option starter string. For the programmer, there's a very definite order in these 'first' arguments, but I doubt the ordinary (or casual) user will find this easy. -- Johan
Re: Getopt::Long wishes (was: RFC: Getopt::Modern)
* Orton, Yves [EMAIL PROTECTED] [2005-06-27 11:25]: Imo it would better to expose a different subroutine name for this. Ie: sub GetOptions { GetOptionsArray([EMAIL PROTECTED],@_); } Sounds like a very good idea to me. * Johan Vromans [EMAIL PROTECTED] [2005-06-27 11:55]: GetOptionsFromArray? I like that name. Regards, -- #Aristotle *AUTOLOAD=*_=sub{s/(.*)::(.*)/print$2,(,$\/, )[defined wantarray]/e;$1}; Just-another-Perl-hacker;
Re: Getopt::Long wishes (was: RFC: Getopt::Modern)
# The following was supposedly scribed by # Johan Vromans # on Monday 27 June 2005 02:46 am: sub GetOptions { GetOptionsArray([EMAIL PROTECTED],@_); } GetOptionsFromArray? That sounds like a great idea. Any chance of it involving an object (and therefore multi-pass support?) --Eric -- Atavism n: The recurrence of any peculiarity or disease of an ancestor in a subsequent generation, usually due to genetic recombination. - http://scratchcomputing.com -
Re: Getopt::Long wishes (was: RFC: Getopt::Modern)
Johan Vromans wrote: You mean, you are going to pass things like STDOUT, STDERR, ENV and so on, to every function that may use them? [1] Global things are intended to be global, I'd say. This is why code using CGI.pm is so hard to wrap, too. Assumptions that globals will always be globals. Then you go and try and do anything vaguely re-entrant and it all falls to pieces. Sam.
RE: Getopt::Long wishes (was: RFC: Getopt::Modern)
Title: RE: Getopt::Long wishes (was: RFC: Getopt::Modern) -) Structured access to the option settings -) Option to pass in something other @ARGV to the arg-processing code. Id be curious what you mean by the first, and Im confused why the obvious solution to the second is not good enough. local @[EMAIL PROTECTED]; Goes a long way you know. Yves
Re: Getopt::Long wishes (was: RFC: Getopt::Modern)
Greetings, On Mon, Jun 20, 2005 at 11:06:49AM +0100, Orton, Yves wrote: -) Structured access to the option settings -) Option to pass in something other @ARGV to the arg-processing code. Id be curious what you mean by the first, I mean the ability to query Getopt::Long, either by an object method in OO mode or through functions, for a list of recognized options their types (e.g., whether int, bool, string or no arg; their linkage, etc.) and Im confused why the obvious solution to the second is not good enough. local @[EMAIL PROTECTED]; Goes a long way you know. It does, and it works, and it is a stylistic thing perhaps, but although global variables can be made to work, the modern phenomenon of function arguments are very popular. Mx.
Re: Getopt::Long wishes (was: RFC: Getopt::Modern)
Martyn J. Pearce [EMAIL PROTECTED] writes: It does, and it works, and it is a stylistic thing perhaps, but although global variables can be made to work, the modern phenomenon of function arguments are very popular. You mean, you are going to pass things like STDOUT, STDERR, ENV and so on, to every function that may use them? [1] Global things are intended to be global, I'd say. -- Johan [1] This reminds me of an anecdote while I was at the University. We were taught programming, and the rules were quite strict. No globals, only formal parameters. They even dictated the exact parameter list. Files were not part of the parameters. So when I pointed out that a particular routine that needed to produce output could not access the file they decided that the file should be kept local to the routine. Now that was fun, since opening and closing a file caused the printing system to print a couple of banner pages. When my program completed, I had a big pile of output, instead of just a couple of pages. They quickly changed the rules after that :-).
Re: Getopt::Long wishes (was: RFC: Getopt::Modern)
* Orton, Yves [EMAIL PROTECTED] [2005-06-20 12:15]: Im confused why the obvious solution to the second is not good enough. local @[EMAIL PROTECTED]; Goes a long way you know. I don’t like that at all, myself. It works, sure, but then so does “local $/”, and guess what’s happening to all the filehandle-specific globals in Perl 6? I don’t see how being able to *optionally* say something like GetOptions( [EMAIL PROTECTED], # ... ); would detract from anything at all. All it takes to implement in GetOptions() are about two lines of code. (With current calling conventions; I did look.) * Johan Vromans [EMAIL PROTECTED] [2005-06-20 14:35]: You mean, you are going to pass things like STDOUT, STDERR, ENV and so on, to every function that may use them? [1] Yeah, and chomp $foo is wasteful – we should teach people to just say do { local *_ = \$foo; chomp; } Hmm, but where the heck does that strange “select FH” fit in anywhere? :-) I think it’s a good default for GetOptions to process @ARGV. Noone will dispute that. I also think it would be a good thing to be able to explicitly pass a different array instead. I can’t see why anyone would dispute that. Regards, -- #Aristotle *AUTOLOAD=*_=sub{s/(.*)::(.*)/print$2,(,$\/, )[defined wantarray]/e;$1}; Just-another-Perl-hacker;
Re: Getopt::Long wishes (was: RFC: Getopt::Modern)
# The following was supposedly scribed by # A. Pagaltzis # on Monday 20 June 2005 08:57 am: I don’t see how being able to *optionally* say something like GetOptions( [EMAIL PROTECTED], # ... ); would detract from anything at all. I don't think you really need to be able to pass a different array to GetOptions(). After all, that really is just meant for parsing command-line arguments, which aren't going to be found anywhere besides @ARGV. What I do think you need is a way to pass a different array to *something*, so that wrapping and reusing is easier: Consider how things change if GetOptions were structured something like the following instead of having all of that tasty parsing logic stuck inside of it. sub GetOptions { my $self = Getopt::Modern-create(@_); return($self-get([EMAIL PROTECTED])); } Now, if you wanted to write a wrapper (or even an api function (ala Tk) that took a mixed list of arguments and options), you would just call $opt-get([EMAIL PROTECTED]) instead of GetOptions(). To me, it mostly comes down to thinking what the heck does ARGV have to do with anything? everytime I see 'local @ARGV = @arglist'. --Eric -- I arise in the morning torn between a desire to improve the world and a desire to enjoy the world. This makes it hard to plan the day. --E.B. White - http://scratchcomputing.com -
Re: Getopt::Long wishes (was: RFC: Getopt::Modern)
Le lundi 20 juin 2005 à 09:09, Eric Wilhelm écrivait: # The following was supposedly scribed by # A. Pagaltzis # on Monday 20 June 2005 08:57 am: I don???t see how being able to *optionally* say something like GetOptions( [EMAIL PROTECTED], # ... ); would detract from anything at all. I don't think you really need to be able to pass a different array to GetOptions(). After all, that really is just meant for parsing command-line arguments, which aren't going to be found anywhere besides @ARGV. Well, that's a strong assumption. Perl::Tidy, for instance, uses Getopt::Long to parse its parameter list, which has nothing to do with @ARGV. And see http://rt.cpan.org/NoAuth/Bug.html?id=7964 for the kind of trouble that happens when a library uses another library that has a global configuration. In that case, local @ARGV = @whatever is not enough. -- Philippe BooK Bruhat The best thing about being apart is getting together again. (Moral from Groo The Wanderer #39 (Epic))
Getopt::Long wishes (was: RFC: Getopt::Modern)
* Johan Vromans [EMAIL PROTECTED] [2005-06-17 17:20]: I can make this information available, if users would be interested. Access to structured data is always nicer than implementing and re-implemeting a parser for its serialized form. So if it doesnt take too much effort, it would be nice to have. I might even need this at some point (Im the current maintainer of Getopt::Auto, though I must admit I have not done much to earn the title yet). One unhappy user against a zillion happy users. Since were at this: the one thing I still fall back to Getopt::Std for is small scripts. I love Getopt::Long, but it incurs a pretty high startup cost. Is there any chance you can play some deferred compilation cards to make it go faster? Of course, its kind of tricky for a module whose code all runs exactly once, at program startup maybe you can isolate the code that implements various features and compile only those which are actually requested/used? Of course, I have no idea what Im talking about, given that I havent taken even a cursory look at the code. I just thought Id throw these out here while were at the topic, before I get distracted by some other shiny ball. Regards, -- #Aristotle *AUTOLOAD=*_=sub{s/(.*)::(.*)/print$2,(,$\/, )[defined wantarray]/e;$1}; Just-another-Perl-hacker;