Re: Getopt::Long wishes (was: RFC: Getopt::Modern)

2005-07-09 Thread Johan Vromans
 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)

2005-07-09 Thread Eric Wilhelm
# 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)

2005-07-05 Thread Johan Vromans
[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)

2005-07-05 Thread Ken Williams


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)

2005-06-27 Thread Johan Vromans
[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)

2005-06-27 Thread Orton, Yves
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)

2005-06-27 Thread Johan Vromans
[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)

2005-06-27 Thread Sam Vilain

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)

2005-06-27 Thread Johan Vromans
[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)

2005-06-27 Thread A. Pagaltzis
* 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)

2005-06-27 Thread Eric Wilhelm
# 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)

2005-06-26 Thread Sam Vilain

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)

2005-06-20 Thread Orton, Yves
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)

2005-06-20 Thread Martyn J. Pearce
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)

2005-06-20 Thread Johan Vromans
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)

2005-06-20 Thread A. Pagaltzis
* 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)

2005-06-20 Thread Eric Wilhelm
# 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)

2005-06-20 Thread Philippe 'BooK' Bruhat
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)

2005-06-17 Thread A. Pagaltzis
* 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;